diff options
-rw-r--r-- | activerecord/lib/active_record/nested_attributes.rb | 16 | ||||
-rw-r--r-- | activerecord/test/cases/nested_attributes_test.rb | 38 | ||||
-rw-r--r-- | activerecord/test/models/pirate.rb | 2 |
3 files changed, 45 insertions, 11 deletions
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index be013a068c..f91e41b535 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -245,7 +245,8 @@ module ActiveRecord # any value for _destroy. # [:limit] # Allows you to specify the maximum number of the associated records that - # can be processed with the nested attributes. If the size of the + # can be processed with the nested attributes. Limit also can be specified as a + # Proc or a Symbol pointing to a method that should return number. If the size of the # nested attributes array exceeds the specified limit, NestedAttributes::TooManyRecords # exception is raised. If omitted, any number associations can be processed. # Note that the :limit option is only applicable to one-to-many associations. @@ -388,8 +389,17 @@ module ActiveRecord raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})" end - if options[:limit] && attributes_collection.size > options[:limit] - raise TooManyRecords, "Maximum #{options[:limit]} records are allowed. Got #{attributes_collection.size} records instead." + limit = case options[:limit] + when Symbol + send(options[:limit]) + when Proc + options[:limit].call + else + options[:limit] + end + + if limit && attributes_collection.size > limit + raise TooManyRecords, "Maximum #{limit} records are allowed. Got #{attributes_collection.size} records instead." end if attributes_collection.is_a? Hash diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index 3a234f0cc1..725cff8f01 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -846,13 +846,7 @@ class TestNestedAttributesOnAHasAndBelongsToManyAssociation < ActiveRecord::Test include NestedAttributesOnACollectionAssociationTests end -class TestNestedAttributesLimit < ActiveRecord::TestCase - def setup - Pirate.accepts_nested_attributes_for :parrots, :limit => 2 - - @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?") - end - +module NestedAttributesLimitTests def teardown Pirate.accepts_nested_attributes_for :parrots, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? } end @@ -876,6 +870,36 @@ class TestNestedAttributesLimit < ActiveRecord::TestCase end end +class TestNestedAttributesLimitNumeric < ActiveRecord::TestCase + def setup + Pirate.accepts_nested_attributes_for :parrots, :limit => 2 + + @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?") + end + + include NestedAttributesLimitTests +end + +class TestNestedAttributesLimitSymbol < ActiveRecord::TestCase + def setup + Pirate.accepts_nested_attributes_for :parrots, :limit => :parrots_limit + + @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?", :parrots_limit => 2) + end + + include NestedAttributesLimitTests +end + +class TestNestedAttributesLimitProc < ActiveRecord::TestCase + def setup + Pirate.accepts_nested_attributes_for :parrots, :limit => proc { 2 } + + @pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?") + end + + include NestedAttributesLimitTests +end + class TestNestedAttributesWithNonStandardPrimaryKeys < ActiveRecord::TestCase fixtures :owners, :pets diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb index 609b9369a9..170fc2ffe3 100644 --- a/activerecord/test/models/pirate.rb +++ b/activerecord/test/models/pirate.rb @@ -53,7 +53,7 @@ class Pirate < ActiveRecord::Base attributes.delete('_reject_me_if_new').present? && !persisted? end - attr_accessor :cancel_save_from_callback + attr_accessor :cancel_save_from_callback, :parrots_limit before_save :cancel_save_callback_method, :if => :cancel_save_from_callback def cancel_save_callback_method false |