forked from ginty/cranky
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Significant refactoring to improve maintainability
- Loading branch information
Ginty
committed
Aug 22, 2010
1 parent
923308b
commit cf1b814
Showing
10 changed files
with
222 additions
and
159 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
require 'crank_it' | ||
require 'cranky' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,106 +1,18 @@ | ||
class Cranky | ||
|
||
VERSION = "0.1.1" | ||
|
||
# Dir.glob("#{File.expand_path(File.dirname(__FILE__))}/*.rb").each do |file| | ||
# require file | ||
# # Auto include all modules found in the directory | ||
# file =~ /.*[\/\\](.*)\.rb/ | ||
# begin | ||
# include $1.to_s.camelcase.constantize | ||
# rescue | ||
# end | ||
# end | ||
|
||
attr_writer :debug | ||
|
||
def initialize | ||
@what = [] | ||
@attrs = [] | ||
@n = 0 | ||
end | ||
|
||
def build(what, attrs={}) | ||
crank_it(what, false, attrs) | ||
end | ||
|
||
def create(what, attrs={}) | ||
crank_it(what, true, attrs) | ||
end | ||
|
||
def reset | ||
self.instance_variables.each do |var| | ||
instance_variable_set(var, nil) | ||
end | ||
initialize | ||
end | ||
|
||
def attributes_for(what, attrs={}) | ||
build(what, attrs).attributes | ||
end | ||
|
||
def debug(what=nil) | ||
if block_given? | ||
@debug = true | ||
yield | ||
@debug = false | ||
elsif what | ||
@debug = true | ||
item = build(what) | ||
@debug = false | ||
item | ||
else | ||
@debug | ||
end | ||
end | ||
|
||
private | ||
|
||
def n | ||
@n += 1 | ||
end | ||
|
||
def inherit(what, attrs={}) | ||
build(what, attrs.merge(options)) | ||
end | ||
|
||
def crank_it(what, save, attrs) | ||
@attrs << attrs; @what << what | ||
item = self.send(what) | ||
@attrs.pop; @what.pop | ||
if @debug && !item.valid? | ||
raise "Oops, the #{what} created by the Factory has the following errors: #{item.errors}" | ||
end | ||
item.save if save | ||
item | ||
end | ||
|
||
def define(attrs={}) | ||
final_attrs = attrs.merge(@attrs.last) | ||
item = get_constant(attrs[:class] ? attrs[:class] : @what.last).new | ||
final_attrs.delete(:class) | ||
# Assign all explicit attributes first | ||
final_attrs.each do |attr, value| | ||
item.send("#{attr}=", value) if item.respond_to?("#{attr}=") && !value.respond_to?("call") | ||
end | ||
# Then call any blocks | ||
final_attrs.each do |attr, value| | ||
item.send("#{attr}=", value.call(item)) if item.respond_to?("#{attr}=") && value.respond_to?("call") | ||
end | ||
item | ||
end | ||
|
||
# Nicked from here: http://gist.github.com/301173 | ||
def get_constant(name_sym) | ||
name = name_sym.to_s.split('_').collect {|s| s.capitalize }.join('') | ||
Object.const_defined?(name) ? Object.const_get(name) : Object.const_missing(name) | ||
end | ||
|
||
def options | ||
@attrs.last | ||
end | ||
|
||
require 'cranky/version' | ||
require 'cranky/job' | ||
require 'cranky/factory' | ||
|
||
# Instantiate a factory, this enables an easy drop in for tests written for Factory Girl | ||
Factory = Cranky::Factory.new unless defined?(Factory) | ||
|
||
# Alternative Cranky specific syntax: | ||
# crank(:user) # equivalent to Factory.build(:user) | ||
# crank!(:user) # equivalent to Factory.create(:user) | ||
def crank(*args) | ||
Factory.build(*args) | ||
end | ||
|
||
Factory = Cranky.new unless defined?(Factory) | ||
def crank!(*args) | ||
Factory.create(*args) | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
module Cranky | ||
class Factory | ||
|
||
attr_writer :debug | ||
|
||
def initialize | ||
# Factory jobs can be nested, i.e. a factory method can itself invoke another factory method to | ||
# build a dependent object. In this case jobs the jobs are pushed into a pipeline and executed | ||
# in a last in first out order. | ||
@pipeline = [] | ||
@n = 0 | ||
@errors = [] | ||
end | ||
|
||
def build(what, overrides={}) | ||
crank_it(what, overrides) | ||
end | ||
|
||
def create(what, overrides={}) | ||
item = build(what, overrides) | ||
item.save | ||
item | ||
end | ||
|
||
# Reset the factory instance, clear all instance variables | ||
def reset | ||
self.instance_variables.each do |var| | ||
instance_variable_set(var, nil) | ||
end | ||
initialize | ||
end | ||
|
||
def attributes_for(what, attrs={}) | ||
build(what, attrs).attributes | ||
end | ||
|
||
# Can be left in your tests as an alternative to build and to warn if your factory method | ||
# ever starts producing invalid instances | ||
def debug(*args) | ||
item = build(*args) | ||
if !item.valid? | ||
raise "Oops, the #{item.class} created by the Factory has the following errors: #{item.errors}" | ||
end | ||
end | ||
|
||
# Same thing for create | ||
def debug!(*args) | ||
item = debug | ||
item.save | ||
item | ||
end | ||
|
||
private | ||
|
||
def n | ||
@n += 1 | ||
end | ||
|
||
def inherit(what, overrides={}) | ||
build(what, overrides.merge(options)) | ||
end | ||
|
||
# Execute the requested factory method, crank out the target object! | ||
def crank_it(what, overrides) | ||
item = "TBD" | ||
new_job(what, overrides) do | ||
item = self.send(what) # Invoke the factory method | ||
end | ||
item | ||
end | ||
|
||
# This method actually makes the required object instance, it gets called by the users factory | ||
# method, where the name 'define' makes more sense than it does here! | ||
def define(defaults={}) | ||
current_job.defaults = defaults | ||
current_job.execute | ||
end | ||
|
||
def current_job | ||
@pipeline.last | ||
end | ||
|
||
# Returns a hash containing any top-level overrides passed in when the current factory was invoked | ||
def options | ||
current_job.overrides | ||
end | ||
|
||
# Adds a new job to the pipeline then yields to the caller to execute it | ||
def new_job(what, overrides) | ||
@pipeline << Job.new(what, overrides) | ||
yield | ||
@pipeline.pop | ||
end | ||
|
||
end | ||
|
||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
module Cranky | ||
class Job | ||
|
||
attr_writer :defaults | ||
attr_reader :overrides | ||
|
||
def initialize(target, overrides={}) | ||
@defaults = {} | ||
@target = target | ||
@overrides = overrides | ||
end | ||
|
||
def attributes | ||
@attributes ||= @defaults.merge(@overrides) | ||
end | ||
|
||
def defaults=(defs) | ||
@attributes = nil # Needs to be re-calculated | ||
@defaults = defs | ||
end | ||
|
||
def execute | ||
item = get_constant(attributes[:class] ? attributes[:class] : @target).new | ||
# Assign all explicit attributes first | ||
attributes.each do |attribute, value| | ||
item.send("#{attribute}=", value) if item.respond_to?("#{attribute}=") && !value.respond_to?("call") | ||
end | ||
# Then call any blocks | ||
attributes.each do |attribute, value| | ||
item.send("#{attribute}=", value.call(item)) if item.respond_to?("#{attribute}=") && value.respond_to?("call") | ||
end | ||
item | ||
end | ||
|
||
private | ||
|
||
# Nicked from here: http://gist.github.com/301173 | ||
def get_constant(name_sym) | ||
name = name_sym.to_s.split('_').collect {|s| s.capitalize }.join('') | ||
Object.const_defined?(name) ? Object.const_get(name) : Object.const_missing(name) | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module Cranky | ||
VERSION = "0.2.0" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.