Permalink
Browse files

Idea for association syntax within dynamic attributes

Breaks in older (3.0, not sure about 3.1) versions of Rails due to how
association assignment is handled.

Problems: order of block variables is reversed between dynamic
attributes and callbacks. If adding this, I'd prefer to maintain order.
Current implementation handles this by, when one block variable,
treating as evaluator like normal. When two are provided, the instance
becomes the first and the second is the evaluator. Not sure how
confusing that is, though.
  • Loading branch information...
1 parent 47c4d11 commit f9eb0452eac6b173bd489ec416679e2e8f1c0426 @joshuaclayton joshuaclayton committed Nov 20, 2012
@@ -11,7 +11,11 @@ def to_proc
block = @block
-> {
- value = block.arity == 1 ? block.call(self) : instance_exec(&block)
+ value = case block.arity
+ when 1 then block.call(self)
+ when 2 then block.call(@instance, self)
+ else instance_exec(&block)
+ end
raise SequenceAbuseError if FactoryGirl::Sequence === value
value
}
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe 'Dynamic attributes' do
+ before do
+ define_model('User', name: :string) do
+ has_many :posts
+ end
+
+ define_model('Post', user_id: :integer) do
+ belongs_to :user
+ end
+
+ FactoryGirl.define do
+ factory :post do
+ user
+ end
+
+ factory :user do
+ posts {|user, e| [e.association(:post, user: user), e.association(:post, user: user)] }
+ end
+ end
+ end
+
+ it 'creates the correct records when calling create' do
+ user = FactoryGirl.create(:user)
+ user.reload
+ user.posts.length.should == 2
+ Post.count.should == 2
+ end
+
+ it 'creates the correct records when calling build' do
+ user = FactoryGirl.build(:user)
+ user.posts.length.should == 2
+ Post.count.should == 2
+ end
+
+ it 'builds stubbed records when calling build_stubbed' do
+ user = FactoryGirl.build_stubbed(:user)
+ user.posts.length.should == 2
+ Post.count.should == 0
+ end
+end
+
@@ -17,13 +17,22 @@
end
context "with a block returning its block-level variable" do
- let(:block) { ->(thing) { thing } }
+ let(:block) { ->(evaluator) { evaluator } }
it "returns self when executing the proc" do
expect(subject.to_proc.call).to eq subject
end
end
+ context "with a block returning its instance variable" do
+ let(:block) { ->(instance, evaluator) { instance } }
+
+ it "returns the instance variable when executing the proc" do
+ subject.instance_variable_set(:@instance, 3)
+ subject.to_proc.call.should == 3
+ end
+ end
+
context "with a block referencing an attribute on the attribute" do
let(:block) { -> { attribute_defined_on_attribute } }
let(:result) { "other attribute value" }

0 comments on commit f9eb045

Please sign in to comment.