提交 68d416a5 编写于 作者: P Pratik Naik

Add a :limit option to specify the maximum number of records that can be...

Add a :limit option to specify the maximum number of records that can be processed by accepts_nested_attributes_for
上级 e94caf07
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
module ActiveRecord module ActiveRecord
module NestedAttributes #:nodoc: module NestedAttributes #:nodoc:
class TooManyRecords < ActiveRecordError
end
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
...@@ -203,6 +206,12 @@ module ClassMethods ...@@ -203,6 +206,12 @@ module ClassMethods
# do not have a <tt>_destroy</tt> value that evaluates to true. # do not have a <tt>_destroy</tt> value that evaluates to true.
# Passing <tt>:all_blank</tt> instead of a Proc will create a proc # Passing <tt>:all_blank</tt> instead of a Proc will create a proc
# that will reject a record where all the attributes are blank. # that will reject a record where all the attributes are blank.
# [:limit]
# Allows you to specify the maximum number of the associated records that
# can be processes with the nested attributes. 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.
# #
# Examples: # Examples:
# # creates avatar_attributes= # # creates avatar_attributes=
...@@ -214,7 +223,7 @@ module ClassMethods ...@@ -214,7 +223,7 @@ module ClassMethods
def accepts_nested_attributes_for(*attr_names) def accepts_nested_attributes_for(*attr_names)
options = { :allow_destroy => false } options = { :allow_destroy => false }
options.update(attr_names.extract_options!) options.update(attr_names.extract_options!)
options.assert_valid_keys(:allow_destroy, :reject_if) options.assert_valid_keys(:allow_destroy, :reject_if, :limit)
attr_names.each do |association_name| attr_names.each do |association_name|
if reflection = reflect_on_association(association_name) if reflection = reflect_on_association(association_name)
...@@ -334,6 +343,10 @@ def assign_nested_attributes_for_collection_association(association_name, attrib ...@@ -334,6 +343,10 @@ def assign_nested_attributes_for_collection_association(association_name, attrib
raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})" raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
end end
if options[:limit] && attributes_collection.size > options[:limit]
raise TooManyRecords, "Maximum #{options[:limit]} records are allowed. Got #{attributes_collection.size} records instead."
end
if attributes_collection.is_a? Hash if attributes_collection.is_a? Hash
attributes_collection = attributes_collection.sort_by { |index, _| index.to_i }.map { |_, attributes| attributes } attributes_collection = attributes_collection.sort_by { |index, _| index.to_i }.map { |_, attributes| attributes }
end end
......
...@@ -603,3 +603,33 @@ def setup ...@@ -603,3 +603,33 @@ def setup
include NestedAttributesOnACollectionAssociationTests include NestedAttributesOnACollectionAssociationTests
end 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
def teardown
Pirate.accepts_nested_attributes_for :parrots, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
end
def test_limit_with_less_records
@pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Big Big Love' } } }
assert_difference('Parrot.count') { @pirate.save! }
end
def test_limit_with_number_exact_records
@pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' }, 'bar' => { :name => 'Blown Away' } } }
assert_difference('Parrot.count', 2) { @pirate.save! }
end
def test_limit_with_exceeding_records
assert_raises(ActiveRecord::NestedAttributes::TooManyRecords) do
@pirate.attributes = { :parrots_attributes => { 'foo' => { :name => 'Lovely Day' },
'bar' => { :name => 'Blown Away' },
'car' => { :name => 'The Happening' }} }
end
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册