diff options
Diffstat (limited to 'activerecord/test/cases/associations')
7 files changed, 420 insertions, 38 deletions
diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb index 1b2e0fc11e..f313a75233 100644 --- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb +++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb @@ -1,18 +1,18 @@ require 'cases/helper' -require 'models/author' require 'models/post' +require 'models/author' require 'models/comment' require 'models/category' require 'models/categorization' +require 'active_support/core_ext/array/random_access' module Remembered - def self.included(base) - base.extend ClassMethods - base.class_eval do - after_create :remember - protected - def remember; self.class.remembered << self; end - end + extend ActiveSupport::Concern + + included do + after_create :remember + protected + def remember; self.class.remembered << self; end end module ClassMethods @@ -66,13 +66,13 @@ class EagerLoadPolyAssocsTest < ActiveRecord::TestCase def setup generate_test_object_graphs end - + def teardown - [Circle, Square, Triangle, PaintColor, PaintTexture, + [Circle, Square, Triangle, PaintColor, PaintTexture, ShapeExpression, NonPolyOne, NonPolyTwo].each do |c| c.delete_all end - + end @@ -127,4 +127,4 @@ class EagerLoadNestedIncludeWithMissingDataTest < ActiveRecord::TestCase Author.all :include => includes, :conditions => {:authors => {:name => @davey_mcdave.name}}, :order => 'categories.name' end end -end
\ No newline at end of file +end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 40723814c5..4cf49be668 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -223,6 +223,18 @@ class EagerAssociationTest < ActiveRecord::TestCase end end + def test_eager_association_loading_with_belongs_to_and_conditions_hash + comments = [] + assert_nothing_raised do + comments = Comment.find(:all, :include => :post, :conditions => {:posts => {:id => 4}}, :limit => 3, :order => 'comments.id') + end + assert_equal 3, comments.length + assert_equal [5,6,7], comments.collect { |c| c.id } + assert_no_queries do + comments.first.post + end + end + def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id') assert_nothing_raised do @@ -577,6 +589,10 @@ class EagerAssociationTest < ActiveRecord::TestCase assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC, posts.id', :limit => 2, :offset => 1) end + def test_limited_eager_with_numeric_in_association + assert_equal people(:david, :susan), Person.find(:all, :include => [:readers, :primary_contact, :number1_fan], :conditions => "number1_fans_people.first_name like 'M%'", :order => 'people.id', :limit => 2, :offset => 0) + end + def test_preload_with_interpolation assert_equal [comments(:greetings)], Post.find(posts(:welcome).id, :include => :comments_with_interpolated_conditions).comments_with_interpolated_conditions end diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 5e8b2cadfc..8dc95806b9 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -24,6 +24,7 @@ require 'models/club' require 'models/member' require 'models/membership' require 'models/sponsor' +require 'active_support/core_ext/string/conversions' class ProjectWithAfterCreateHook < ActiveRecord::Base set_table_name 'projects' diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 5df74fcdcd..d99424f9cd 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1023,6 +1023,45 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert firm.clients.loaded? end + def test_calling_many_should_count_instead_of_loading_association + firm = companies(:first_firm) + assert_queries(1) do + firm.clients.many? # use count query + end + assert !firm.clients.loaded? + end + + def test_calling_many_on_loaded_association_should_not_use_query + firm = companies(:first_firm) + firm.clients.collect # force load + assert_no_queries { assert firm.clients.many? } + end + + def test_calling_many_should_defer_to_collection_if_using_a_block + firm = companies(:first_firm) + assert_queries(1) do + firm.clients.expects(:size).never + firm.clients.many? { true } + end + assert firm.clients.loaded? + end + + def test_calling_many_should_return_false_if_none_or_one + firm = companies(:another_firm) + assert !firm.clients_like_ms.many? + assert_equal 0, firm.clients_like_ms.size + + firm = companies(:first_firm) + assert !firm.limited_clients.many? + assert_equal 1, firm.limited_clients.size + end + + def test_calling_many_should_return_true_if_more_than_one + firm = companies(:first_firm) + assert firm.clients.many? + assert_equal 2, firm.clients.size + end + def test_joins_with_namespaced_model_should_use_correct_type old = ActiveRecord::Base.store_full_sti_class ActiveRecord::Base.store_full_sti_class = true diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 97efca7891..4254badef2 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -13,7 +13,7 @@ require 'models/pet' require 'models/toy' class HasManyThroughAssociationsTest < ActiveRecord::TestCase - fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys + fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys, :jobs, :references def test_associate_existing assert_queries(2) { posts(:thinking);people(:david) } @@ -23,49 +23,49 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase assert_queries(1) do posts(:thinking).people << people(:david) end - + assert_queries(1) do assert posts(:thinking).people.include?(people(:david)) end - + assert posts(:thinking).reload.people(true).include?(people(:david)) end def test_associating_new assert_queries(1) { posts(:thinking) } new_person = nil # so block binding catches it - + assert_queries(0) do new_person = Person.new :first_name => 'bob' end - + # Associating new records always saves them # Thus, 1 query for the new person record, 1 query for the new join table record assert_queries(2) do posts(:thinking).people << new_person end - + assert_queries(1) do assert posts(:thinking).people.include?(new_person) end - + assert posts(:thinking).reload.people(true).include?(new_person) end def test_associate_new_by_building assert_queries(1) { posts(:thinking) } - + assert_queries(0) do posts(:thinking).people.build(:first_name=>"Bob") posts(:thinking).people.new(:first_name=>"Ted") end - + # Should only need to load the association once assert_queries(1) do assert posts(:thinking).people.collect(&:first_name).include?("Bob") assert posts(:thinking).people.collect(&:first_name).include?("Ted") end - + # 2 queries for each new record (1 to save the record itself, 1 for the join model) # * 2 new records = 4 # + 1 query to save the actual post = 5 @@ -73,27 +73,27 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase posts(:thinking).body += '-changed' posts(:thinking).save end - + assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Bob") assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Ted") end def test_delete_association assert_queries(2){posts(:welcome);people(:michael); } - + assert_queries(1) do posts(:welcome).people.delete(people(:michael)) end - + assert_queries(1) do assert posts(:welcome).people.empty? end - + assert posts(:welcome).reload.people(true).empty? end def test_destroy_association - assert_difference "Person.count", -1 do + assert_difference ["Person.count", "Reader.count"], -1 do posts(:welcome).people.destroy(people(:michael)) end @@ -102,7 +102,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase end def test_destroy_all - assert_difference "Person.count", -1 do + assert_difference ["Person.count", "Reader.count"], -1 do posts(:welcome).people.destroy_all end @@ -110,38 +110,44 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase assert posts(:welcome).people(true).empty? end + def test_should_raise_exception_for_destroying_mismatching_records + assert_no_difference ["Person.count", "Reader.count"] do + assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:welcome).people.destroy(posts(:thinking)) } + end + end + def test_replace_association assert_queries(4){posts(:welcome);people(:david);people(:michael); posts(:welcome).people(true)} - + # 1 query to delete the existing reader (michael) # 1 query to associate the new reader (david) assert_queries(2) do posts(:welcome).people = [people(:david)] end - + assert_queries(0){ assert posts(:welcome).people.include?(people(:david)) assert !posts(:welcome).people.include?(people(:michael)) } - + assert posts(:welcome).reload.people(true).include?(people(:david)) assert !posts(:welcome).reload.people(true).include?(people(:michael)) end def test_associate_with_create assert_queries(1) { posts(:thinking) } - + # 1 query for the new record, 1 for the join table record # No need to update the actual collection yet! assert_queries(2) do posts(:thinking).people.create(:first_name=>"Jeb") end - + # *Now* we actually need the collection so it's loaded assert_queries(1) do assert posts(:thinking).people.collect(&:first_name).include?("Jeb") end - + assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Jeb") end @@ -159,15 +165,15 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase def test_clear_associations assert_queries(2) { posts(:welcome);posts(:welcome).people(true) } - + assert_queries(1) do posts(:welcome).people.clear end - + assert_queries(0) do assert posts(:welcome).people.empty? end - + assert posts(:welcome).reload.people(true).empty? end diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb index 12c598751b..ab6e6d20fc 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -43,7 +43,14 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase @member.reload end end - + + def test_set_record_to_nil_should_delete_association + @member.club = nil + @member.reload + assert_equal nil, @member.current_membership + assert_nil @member.club + end + def test_has_one_through_polymorphic assert_equal clubs(:moustache_club), @member.sponsor_club end diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb new file mode 100644 index 0000000000..47f83db112 --- /dev/null +++ b/activerecord/test/cases/associations/inverse_associations_test.rb @@ -0,0 +1,313 @@ +require "cases/helper" +require 'models/man' +require 'models/face' +require 'models/interest' +require 'models/zine' +require 'models/club' +require 'models/sponsor' + +class InverseAssociationTests < ActiveRecord::TestCase + def test_should_allow_for_inverse_of_options_in_associations + assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_many') do + Class.new(ActiveRecord::Base).has_many(:wheels, :inverse_of => :car) + end + + assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_one') do + Class.new(ActiveRecord::Base).has_one(:engine, :inverse_of => :car) + end + + assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on belongs_to') do + Class.new(ActiveRecord::Base).belongs_to(:car, :inverse_of => :driver) + end + end + + def test_should_be_able_to_ask_a_reflection_if_it_has_an_inverse + has_one_with_inverse_ref = Man.reflect_on_association(:face) + assert has_one_with_inverse_ref.respond_to?(:has_inverse?) + assert has_one_with_inverse_ref.has_inverse? + + has_many_with_inverse_ref = Man.reflect_on_association(:interests) + assert has_many_with_inverse_ref.respond_to?(:has_inverse?) + assert has_many_with_inverse_ref.has_inverse? + + belongs_to_with_inverse_ref = Face.reflect_on_association(:man) + assert belongs_to_with_inverse_ref.respond_to?(:has_inverse?) + assert belongs_to_with_inverse_ref.has_inverse? + + has_one_without_inverse_ref = Club.reflect_on_association(:sponsor) + assert has_one_without_inverse_ref.respond_to?(:has_inverse?) + assert !has_one_without_inverse_ref.has_inverse? + + has_many_without_inverse_ref = Club.reflect_on_association(:memberships) + assert has_many_without_inverse_ref.respond_to?(:has_inverse?) + assert !has_many_without_inverse_ref.has_inverse? + + belongs_to_without_inverse_ref = Sponsor.reflect_on_association(:sponsor_club) + assert belongs_to_without_inverse_ref.respond_to?(:has_inverse?) + assert !belongs_to_without_inverse_ref.has_inverse? + end + + def test_should_be_able_to_ask_a_reflection_what_it_is_the_inverse_of + has_one_ref = Man.reflect_on_association(:face) + assert has_one_ref.respond_to?(:inverse_of) + + has_many_ref = Man.reflect_on_association(:interests) + assert has_many_ref.respond_to?(:inverse_of) + + belongs_to_ref = Face.reflect_on_association(:man) + assert belongs_to_ref.respond_to?(:inverse_of) + end + + def test_inverse_of_method_should_supply_the_actual_reflection_instance_it_is_the_inverse_of + has_one_ref = Man.reflect_on_association(:face) + assert_equal Face.reflect_on_association(:man), has_one_ref.inverse_of + + has_many_ref = Man.reflect_on_association(:interests) + assert_equal Interest.reflect_on_association(:man), has_many_ref.inverse_of + + belongs_to_ref = Face.reflect_on_association(:man) + assert_equal Man.reflect_on_association(:face), belongs_to_ref.inverse_of + end + + def test_associations_with_no_inverse_of_should_return_nil + has_one_ref = Club.reflect_on_association(:sponsor) + assert_nil has_one_ref.inverse_of + + has_many_ref = Club.reflect_on_association(:memberships) + assert_nil has_many_ref.inverse_of + + belongs_to_ref = Sponsor.reflect_on_association(:sponsor_club) + assert_nil belongs_to_ref.inverse_of + end +end + +class InverseHasOneTests < ActiveRecord::TestCase + fixtures :men, :faces + + def test_parent_instance_should_be_shared_with_child_on_find + m = Man.find(:first) + f = m.face + assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance" + f.man.name = 'Mungo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance" + end + + + def test_parent_instance_should_be_shared_with_eager_loaded_child_on_find + m = Man.find(:first, :include => :face) + f = m.face + assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance" + f.man.name = 'Mungo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance" + + m = Man.find(:first, :include => :face, :order => 'faces.id') + f = m.face + assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance" + f.man.name = 'Mungo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance" + end + + def test_parent_instance_should_be_shared_with_newly_built_child + m = Man.find(:first) + f = m.build_face(:description => 'haunted') + assert_not_nil f.man + assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance" + f.man.name = 'Mungo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to just-built-child-owned instance" + end + + def test_parent_instance_should_be_shared_with_newly_created_child + m = Man.find(:first) + f = m.create_face(:description => 'haunted') + assert_not_nil f.man + assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance" + f.man.name = 'Mungo' + assert_equal m.name, f.man.name, "Name of man should be the same after changes to newly-created-child-owned instance" + end + + def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error + assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.find(:first).dirty_face } + end +end + +class InverseHasManyTests < ActiveRecord::TestCase + fixtures :men, :interests + + def test_parent_instance_should_be_shared_with_every_child_on_find + m = Man.find(:first) + is = m.interests + is.each do |i| + assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance" + i.man.name = 'Mungo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance" + end + end + + def test_parent_instance_should_be_shared_with_eager_loaded_children + m = Man.find(:first, :include => :interests) + is = m.interests + is.each do |i| + assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance" + i.man.name = 'Mungo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance" + end + + m = Man.find(:first, :include => :interests, :order => 'interests.id') + is = m.interests + is.each do |i| + assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance" + i.man.name = 'Mungo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance" + end + + end + + def test_parent_instance_should_be_shared_with_newly_built_child + m = Man.find(:first) + i = m.interests.build(:topic => 'Industrial Revolution Re-enactment') + assert_not_nil i.man + assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance" + i.man.name = 'Mungo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to just-built-child-owned instance" + end + + def test_parent_instance_should_be_shared_with_newly_created_child + m = Man.find(:first) + i = m.interests.create(:topic => 'Industrial Revolution Re-enactment') + assert_not_nil i.man + assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance" + i.man.name = 'Mungo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance" + end + + def test_parent_instance_should_be_shared_with_poked_in_child + m = Man.find(:first) + i = Interest.create(:topic => 'Industrial Revolution Re-enactment') + m.interests << i + assert_not_nil i.man + assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance" + m.name = 'Bongo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance" + i.man.name = 'Mungo' + assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance" + end + + def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error + assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.find(:first).secret_interests } + end +end + +class InverseBelongsToTests < ActiveRecord::TestCase + fixtures :men, :faces, :interests + + def test_child_instance_should_be_shared_with_parent_on_find + f = Face.find(:first) + m = f.man + assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance" + f.description = 'gormless' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance" + m.face.description = 'pleasing' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance" + end + + def test_eager_loaded_child_instance_should_be_shared_with_parent_on_find + f = Face.find(:first, :include => :man) + m = f.man + assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance" + f.description = 'gormless' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance" + m.face.description = 'pleasing' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance" + + + f = Face.find(:first, :include => :man, :order => 'men.id') + m = f.man + assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance" + f.description = 'gormless' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance" + m.face.description = 'pleasing' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance" + end + + def test_child_instance_should_be_shared_with_newly_built_parent + f = Face.find(:first) + m = f.build_man(:name => 'Charles') + assert_not_nil m.face + assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance" + f.description = 'gormless' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance" + m.face.description = 'pleasing' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to just-built-parent-owned instance" + end + + def test_child_instance_should_be_shared_with_newly_created_parent + f = Face.find(:first) + m = f.create_man(:name => 'Charles') + assert_not_nil m.face + assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance" + f.description = 'gormless' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance" + m.face.description = 'pleasing' + assert_equal f.description, m.face.description, "Description of face should be the same after changes to newly-created-parent-owned instance" + end + + def test_should_not_try_to_set_inverse_instances_when_the_inverse_is_a_has_many + i = Interest.find(:first) + m = i.man + assert_not_nil m.interests + iz = m.interests.detect {|iz| iz.id == i.id} + assert_not_nil iz + assert_equal i.topic, iz.topic, "Interest topics should be the same before changes to child" + i.topic = 'Eating cheese with a spoon' + assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to child" + iz.topic = 'Cow tipping' + assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to parent-owned instance" + end + + def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error + assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.find(:first).horrible_man } + end +end + +# NOTE - these tests might not be meaningful, ripped as they were from the parental_control plugin +# which would guess the inverse rather than look for an explicit configuration option. +class InverseMultipleHasManyInversesForSameModel < ActiveRecord::TestCase + fixtures :men, :interests, :zines + + def test_that_we_can_load_associations_that_have_the_same_reciprocal_name_from_different_models + assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do + i = Interest.find(:first) + z = i.zine + m = i.man + end + end + + def test_that_we_can_create_associations_that_have_the_same_reciprocal_name_from_different_models + assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do + i = Interest.find(:first) + i.build_zine(:title => 'Get Some in Winter! 2008') + i.build_man(:name => 'Gordon') + i.save! + end + end +end |