1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# frozen_string_literal: true
require "cases/helper"
require "active_support/core_ext/hash/indifferent_access"
require "active_support/hash_with_indifferent_access"
class AttributeAssignmentTest < ActiveModel::TestCase
class Model
include ActiveModel::AttributeAssignment
attr_accessor :name, :description
def initialize(attributes = {})
assign_attributes(attributes)
end
def broken_attribute=(value)
raise ErrorFromAttributeWriter
end
# TODO Change this to private once we've dropped Ruby 2.2 support.
# Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_writer :metadata
end
class ErrorFromAttributeWriter < StandardError
end
class ProtectedParams
attr_accessor :permitted
alias :permitted? :permitted
delegate :keys, :key?, :has_key?, :empty?, to: :@parameters
def initialize(attributes)
@parameters = attributes.with_indifferent_access
@permitted = false
end
def permit!
@permitted = true
self
end
def [](key)
@parameters[key]
end
def to_h
@parameters
end
def stringify_keys
dup
end
def dup
super.tap do |duplicate|
duplicate.instance_variable_set :@permitted, permitted?
end
end
end
test "simple assignment" do
model = Model.new
model.assign_attributes(name: "hello", description: "world")
assert_equal "hello", model.name
assert_equal "world", model.description
end
test "assign non-existing attribute" do
model = Model.new
error = assert_raises(ActiveModel::UnknownAttributeError) do
model.assign_attributes(hz: 1)
end
assert_equal model, error.record
assert_equal "hz", error.attribute
end
test "assign private attribute" do
model = Model.new
assert_raises(ActiveModel::UnknownAttributeError) do
model.assign_attributes(metadata: { a: 1 })
end
end
test "does not swallow errors raised in an attribute writer" do
assert_raises(ErrorFromAttributeWriter) do
Model.new(broken_attribute: 1)
end
end
test "an ArgumentError is raised if a non-hash-like object is passed" do
assert_raises(ArgumentError) do
Model.new(1)
end
end
test "forbidden attributes cannot be used for mass assignment" do
params = ProtectedParams.new(name: "Guille", description: "m")
assert_raises(ActiveModel::ForbiddenAttributesError) do
Model.new(params)
end
end
test "permitted attributes can be used for mass assignment" do
params = ProtectedParams.new(name: "Guille", description: "desc")
params.permit!
model = Model.new(params)
assert_equal "Guille", model.name
assert_equal "desc", model.description
end
test "regular hash should still be used for mass assignment" do
model = Model.new(name: "Guille", description: "m")
assert_equal "Guille", model.name
assert_equal "m", model.description
end
test "assigning no attributes should not raise, even if the hash is un-permitted" do
model = Model.new
assert_nil model.assign_attributes(ProtectedParams.new({}))
end
end
|