Skip to content

Commit

Permalink
Added ability to assign attributes via a block
Browse files Browse the repository at this point in the history
  • Loading branch information
Ginty committed May 27, 2010
1 parent d0b4c44 commit efc07f4
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
13 changes: 11 additions & 2 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ So a nice tip is to implement default associations like this (assuming you're us
# Return the default address if it already exists, or call the address factory to make one
def default_address
# If the default address exists, but has been cleared from the database...
@default_address = nil if @default_address && !Account.exists?(@default_address.id)
@default_address = nil if @default_address && !Address.exists?(@default_address.id)
@default_address ||= create(:address)
end

Expand Down Expand Up @@ -164,7 +164,16 @@ Most of your factories are likely to simply define a list of mimimum attribute v

Note that you don't have to worry about handling the overrides here, they will be applied automatically if present, just define the defaults.

The best thing about this is that there are no pesky blocks to worry about. The define argument is just a regular hash, you have complete freedom to choose how to generate the values to be passed into it.
The define argument is just a regular hash, you have complete freedom to choose how to generate the values to be passed into it.

If you like you can generate attributes with a block:

def user
define :name => "Jimmy",
:email => lambda{|u| "#{u.name.downcase}@home.com"},
:role => "pleb",
:address => default_address
end

The define method will return the object, you can grab this for additional manipulation as you would expect...

Expand Down
8 changes: 6 additions & 2 deletions lib/cranky.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,15 @@ def crank_it(what, save, attrs)

def define(attrs={})
final_attrs = attrs.merge(@attrs.last)
#item = (attrs[:class] ? attrs[:class] : @what.last).to_s.camelcase.constantize.new
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}=")
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
Expand Down
7 changes: 7 additions & 0 deletions spec/cranky_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@
Factory.build(:user).argument_received.should == nil
Factory.build(:user, :argument_supplied => true).argument_received.should == true
end

it "should allow blocks to be passed into the define method" do
Factory.build(:user, :name => "jenny", :email => lambda{ |u| "#{u.name}@home.com" }).email.should == "[email protected]"
Factory.build(:user, :name => lambda{"jimmy" + " cranky"}).name.should == "jimmy cranky"
Factory.build(:user, :name => "jenny", :email => Proc.new{ |u| "#{u.name}@home.com" }).email.should == "[email protected]"
Factory.build(:user, :name => Proc.new{"jimmy" + " cranky"}).name.should == "jimmy cranky"
end

end

0 comments on commit efc07f4

Please sign in to comment.