Skip to content

Commit 4007965

Browse files
committed
Use each_pair in ActiveModel::AttributeAssignment#_assign_attributes
`ActiveModel::AttributeAssignment#assign_attributes` checks if the argument responds to `each_pair`, and raises an exception if it does not. However, in `_assign_attributes`, the argument is enumerated using `each`. As a result, if the argument has `each_pair` but not `each`, this error check results in a false negative. (An example of such an object is `OpenStruct`.)
1 parent 32dcdca commit 4007965

File tree

2 files changed

+11
-1
lines changed

2 files changed

+11
-1
lines changed

activemodel/lib/active_model/attribute_assignment.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def attribute_writer_missing(name, value)
5959

6060
private
6161
def _assign_attributes(attributes)
62-
attributes.each do |k, v|
62+
attributes.each_pair do |k, v|
6363
_assign_attribute(k, v)
6464
end
6565
end

activemodel/test/cases/attribute_assignment_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,14 @@ def attribute_writer_missing(name, value) = @assigned_attributes[name] = value
148148
model = Model.new
149149
assert_nil model.assign_attributes(ProtectedParams.new({}))
150150
end
151+
152+
test "passing an object with each_pair but without each" do
153+
model = Model.new
154+
h = { name: "hello", description: "world" }
155+
h.instance_eval { undef :each }
156+
model.assign_attributes(h)
157+
158+
assert_equal "hello", model.name
159+
assert_equal "world", model.description
160+
end
151161
end

0 commit comments

Comments
 (0)