granite-form 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -1
  3. data/.github/workflows/ruby.yml +3 -5
  4. data/.rubocop.yml +26 -48
  5. data/.rubocop_todo.yml +304 -27
  6. data/Appraisals +1 -1
  7. data/CHANGELOG.md +15 -2
  8. data/gemfiles/{rails.5.0.gemfile → rails.7.1.gemfile} +3 -3
  9. data/granite-form.gemspec +6 -5
  10. data/lib/granite/form/active_record/associations.rb +4 -3
  11. data/lib/granite/form/config.rb +1 -1
  12. data/lib/granite/form/errors.rb +34 -32
  13. data/lib/granite/form/extensions.rb +2 -1
  14. data/lib/granite/form/model/associations/base.rb +6 -2
  15. data/lib/granite/form/model/associations/collection/embedded.rb +1 -1
  16. data/lib/granite/form/model/associations/collection/proxy.rb +3 -3
  17. data/lib/granite/form/model/associations/embeds_any.rb +1 -1
  18. data/lib/granite/form/model/associations/embeds_many.rb +15 -11
  19. data/lib/granite/form/model/associations/embeds_one.rb +9 -8
  20. data/lib/granite/form/model/associations/nested_attributes.rb +60 -32
  21. data/lib/granite/form/model/associations/persistence_adapters/active_record/referenced_proxy.rb +2 -1
  22. data/lib/granite/form/model/associations/persistence_adapters/active_record.rb +7 -6
  23. data/lib/granite/form/model/associations/persistence_adapters/base.rb +8 -4
  24. data/lib/granite/form/model/associations/references_any.rb +1 -1
  25. data/lib/granite/form/model/associations/references_many.rb +3 -2
  26. data/lib/granite/form/model/associations/references_one.rb +1 -1
  27. data/lib/granite/form/model/associations/reflections/base.rb +3 -2
  28. data/lib/granite/form/model/associations/reflections/embeds_any.rb +4 -4
  29. data/lib/granite/form/model/associations/reflections/embeds_many.rb +4 -1
  30. data/lib/granite/form/model/associations/reflections/embeds_one.rb +4 -1
  31. data/lib/granite/form/model/associations/reflections/references_any.rb +6 -6
  32. data/lib/granite/form/model/associations/reflections/references_many.rb +1 -1
  33. data/lib/granite/form/model/associations/reflections/references_one.rb +1 -1
  34. data/lib/granite/form/model/associations/validations.rb +6 -6
  35. data/lib/granite/form/model/associations.rb +6 -4
  36. data/lib/granite/form/model/attributes/attribute.rb +1 -0
  37. data/lib/granite/form/model/attributes/base.rb +9 -7
  38. data/lib/granite/form/model/attributes/reference_one.rb +1 -1
  39. data/lib/granite/form/model/attributes/reflections/base/build_type_definition.rb +2 -1
  40. data/lib/granite/form/model/attributes/reflections/represents/build_type_definition.rb +2 -2
  41. data/lib/granite/form/model/attributes/represents.rb +1 -1
  42. data/lib/granite/form/model/attributes.rb +21 -13
  43. data/lib/granite/form/model/conventions.rb +1 -1
  44. data/lib/granite/form/model/persistence.rb +1 -1
  45. data/lib/granite/form/model/primary.rb +1 -1
  46. data/lib/granite/form/model/representation.rb +4 -4
  47. data/lib/granite/form/model/scopes.rb +5 -5
  48. data/lib/granite/form/model/validations.rb +4 -3
  49. data/lib/granite/form/types/active_support/time_zone.rb +1 -1
  50. data/lib/granite/form/types/array.rb +1 -1
  51. data/lib/granite/form/types/big_decimal.rb +1 -1
  52. data/lib/granite/form/types/boolean.rb +1 -1
  53. data/lib/granite/form/types/date.rb +1 -1
  54. data/lib/granite/form/types/date_time.rb +1 -1
  55. data/lib/granite/form/types/dictionary.rb +1 -1
  56. data/lib/granite/form/types/float.rb +1 -1
  57. data/lib/granite/form/types/has_subtype.rb +1 -0
  58. data/lib/granite/form/types/hash_with_action_controller_parameters.rb +2 -2
  59. data/lib/granite/form/types/integer.rb +1 -1
  60. data/lib/granite/form/types/object.rb +2 -1
  61. data/lib/granite/form/types/string.rb +1 -1
  62. data/lib/granite/form/types/time.rb +1 -1
  63. data/lib/granite/form/types/uuid.rb +1 -1
  64. data/lib/granite/form/util.rb +1 -1
  65. data/lib/granite/form/version.rb +1 -1
  66. data/spec/granite/form/active_record/associations_spec.rb +35 -13
  67. data/spec/granite/form/config_spec.rb +8 -4
  68. data/spec/granite/form/model/associations/embeds_many_spec.rb +99 -51
  69. data/spec/granite/form/model/associations/embeds_one_spec.rb +48 -25
  70. data/spec/granite/form/model/associations/persistence_adapters/active_record_spec.rb +12 -7
  71. data/spec/granite/form/model/associations/references_many_spec.rb +51 -10
  72. data/spec/granite/form/model/associations/references_one_spec.rb +17 -6
  73. data/spec/granite/form/model/associations/reflections/embeds_many_spec.rb +51 -16
  74. data/spec/granite/form/model/associations/reflections/embeds_one_spec.rb +19 -9
  75. data/spec/granite/form/model/associations/reflections/references_many_spec.rb +67 -15
  76. data/spec/granite/form/model/associations/reflections/references_one_spec.rb +34 -11
  77. data/spec/granite/form/model/associations/validations_spec.rb +16 -5
  78. data/spec/granite/form/model/associations_spec.rb +28 -9
  79. data/spec/granite/form/model/attributes/attribute_spec.rb +33 -11
  80. data/spec/granite/form/model/attributes/base_spec.rb +26 -2
  81. data/spec/granite/form/model/attributes/reflections/attribute_spec.rb +1 -0
  82. data/spec/granite/form/model/attributes/reflections/base_spec.rb +1 -0
  83. data/spec/granite/form/model/attributes/reflections/represents/build_type_definition_spec.rb +3 -1
  84. data/spec/granite/form/model/attributes/reflections/represents_spec.rb +2 -2
  85. data/spec/granite/form/model/attributes/represents_spec.rb +2 -2
  86. data/spec/granite/form/model/attributes_spec.rb +76 -36
  87. data/spec/granite/form/model/dirty_spec.rb +3 -0
  88. data/spec/granite/form/model/persistence_spec.rb +15 -5
  89. data/spec/granite/form/model/primary_spec.rb +17 -2
  90. data/spec/granite/form/model/representation_spec.rb +13 -3
  91. data/spec/granite/form/model/scopes_spec.rb +8 -3
  92. data/spec/granite/form/model/validations/associated_spec.rb +20 -6
  93. data/spec/granite/form/model/validations/nested_spec.rb +30 -14
  94. data/spec/granite/form/model/validations_spec.rb +1 -1
  95. data/spec/granite/form/model_spec.rb +1 -0
  96. data/spec/granite/form/types/collection_spec.rb +2 -1
  97. data/spec/granite/form/types/date_spec.rb +1 -1
  98. data/spec/granite/form/types/date_time_spec.rb +0 -2
  99. data/spec/granite/form/types/dictionary_spec.rb +1 -0
  100. data/spec/granite/form/types/has_subtype_spec.rb +6 -1
  101. data/spec/granite/form/types/hash_with_action_controller_parameters_spec.rb +1 -1
  102. data/spec/granite/form/types/object_spec.rb +2 -0
  103. data/spec/granite/form/types/time_spec.rb +0 -2
  104. data/spec/granite/form/util_spec.rb +6 -3
  105. data/spec/support/active_record.rb +13 -0
  106. data/spec/support/shared/nested_attribute_examples.rb +110 -54
  107. metadata +28 -16
  108. data/gemfiles/rails.5.1.gemfile +0 -14
  109. data/gemfiles/rails.5.2.gemfile +0 -14
@@ -14,6 +14,7 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsMany do
14
14
  embeds_many :projects
15
15
  end
16
16
  end
17
+
17
18
  let(:user) { User.new }
18
19
 
19
20
  context ':read, :write' do
@@ -24,14 +25,14 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsMany do
24
25
 
25
26
  attribute :name
26
27
  embeds_many :projects,
27
- read: lambda { |reflection, object|
28
- value = object.instance_variable_get("@_value_#{reflection.name}")
29
- JSON.parse(value) if value.present?
30
- },
31
- write: lambda { |reflection, object, value|
32
- value = value.to_json if value
33
- object.instance_variable_set("@_value_#{reflection.name}", value)
34
- }
28
+ read: lambda { |reflection, object|
29
+ value = object.instance_variable_get("@_value_#{reflection.name}")
30
+ JSON.parse(value) if value.present?
31
+ },
32
+ write: lambda { |reflection, object, value|
33
+ value = value.to_json if value
34
+ object.instance_variable_set("@_value_#{reflection.name}", value)
35
+ }
35
36
  end
36
37
  end
37
38
 
@@ -55,16 +56,18 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsMany do
55
56
 
56
57
  describe '#build' do
57
58
  let(:project) { Project.new title: 'Project' }
59
+
58
60
  specify { expect(user.projects.build(title: 'Project')).to eq(project) }
59
61
  specify { expect { user.projects.build(title: 'Project') }.to change { user.projects }.from([]).to([project]) }
60
62
  end
61
63
 
62
64
  describe '#reload' do
63
65
  let(:project) { Project.new title: 'Project' }
66
+
64
67
  before do
65
- user.write_attribute(:projects, [{title: 'Project'}])
68
+ user.write_attribute(:projects, [{ title: 'Project' }])
69
+ user.projects.build
66
70
  end
67
- before { user.projects.build }
68
71
 
69
72
  specify { expect(user.projects.count).to eq(2) }
70
73
  specify { expect(user.projects.reload).to eq([project]) }
@@ -72,26 +75,42 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsMany do
72
75
 
73
76
  describe '#concat' do
74
77
  let(:project) { Project.new title: 'Project' }
78
+
75
79
  specify { expect { user.projects.concat project }.to change { user.projects }.from([]).to([project]) }
76
- specify { expect { user.projects.concat project, 'string' }.to raise_error Granite::Form::AssociationTypeMismatch }
80
+
81
+ specify do
82
+ expect do
83
+ user.projects.concat project, 'string'
84
+ end.to raise_error Granite::Form::AssociationTypeMismatch
85
+ end
77
86
 
78
87
  context do
79
88
  let(:other) { Project.new title: 'Other' }
89
+
80
90
  before { user.projects = [other] }
81
- specify { expect { user.projects.concat project }.to change { user.projects }.from([other]).to([other, project]) }
91
+
92
+ specify do
93
+ expect { user.projects.concat project }
94
+ .to change { user.projects }
95
+ .from([other])
96
+ .to([other, project])
97
+ end
82
98
  end
83
99
  end
84
100
  end
85
101
 
86
102
  describe '#projects=' do
87
103
  let(:project) { Project.new title: 'Project' }
104
+
88
105
  specify { expect { user.projects = [] }.not_to change { user.projects }.from([]) }
89
106
  specify { expect { user.projects = [project] }.to change { user.projects }.from([]).to([project]) }
90
107
  specify { expect { user.projects = [project, 'string'] }.to raise_error Granite::Form::AssociationTypeMismatch }
91
108
 
92
109
  context do
93
110
  let(:other) { Project.new title: 'Other' }
111
+
94
112
  before { user.projects = [other] }
113
+
95
114
  specify { expect { user.projects = [project] }.to change { user.projects }.from([other]).to([project]) }
96
115
  specify { expect { user.projects = [] }.to change { user.projects }.from([other]).to([]) }
97
116
  end
@@ -112,8 +131,18 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsMany do
112
131
 
113
132
  specify { expect(User.reflect_on_association(:projects).klass).to eq(User::Project) }
114
133
  specify { expect(User.new.projects).to eq([]) }
115
- specify { expect(User.new.tap { |u| u.projects.build(title: 'Project') }.projects).to be_a(Granite::Form::Model::Associations::Collection::Embedded) }
116
- specify { expect(User.new.tap { |u| u.projects.build(title: 'Project') }.projects).to match([have_attributes(title: 'Project')]) }
134
+
135
+ specify do
136
+ user = User.new
137
+ user.projects.build(title: 'Project')
138
+ expect(user.projects).to be_a(Granite::Form::Model::Associations::Collection::Embedded)
139
+ end
140
+
141
+ specify do
142
+ user = User.new
143
+ user.projects.build(title: 'Project')
144
+ expect(user.projects).to match([have_attributes(title: 'Project')])
145
+ end
117
146
  end
118
147
 
119
148
  context do
@@ -130,8 +159,14 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsMany do
130
159
 
131
160
  specify { expect(User.reflect_on_association(:projects).klass).to eq(User::Project) }
132
161
  specify { expect(User.new.projects).to eq([]) }
133
- specify { expect(User.new.tap { |u| u.projects.build(title: 'Project') }.projects).to be_a(Granite::Form::Model::Associations::Collection::Embedded) }
134
- specify { expect(User.new.tap { |u| u.projects.build(title: 'Project') }.projects).to match([have_attributes(title: 'Project', value: nil)]) }
162
+
163
+ specify do
164
+ user = User.new
165
+ user.projects.build(title: 'Project')
166
+ expect(user.projects)
167
+ .to be_a(Granite::Form::Model::Associations::Collection::Embedded)
168
+ .and match([have_attributes(title: 'Project', value: nil)])
169
+ end
135
170
  end
136
171
  end
137
172
  end
@@ -15,6 +15,7 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsOne do
15
15
  embeds_one :author
16
16
  end
17
17
  end
18
+
18
19
  let(:book) { Book.new }
19
20
 
20
21
  specify { expect(book.author).to be_nil }
@@ -27,14 +28,14 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsOne do
27
28
 
28
29
  attribute :title
29
30
  embeds_one :author,
30
- read: lambda { |reflection, object|
31
- value = object.instance_variable_get("@_value_#{reflection.name}")
32
- JSON.parse(value) if value.present?
33
- },
34
- write: lambda { |reflection, object, value|
35
- value = value.to_json if value
36
- object.instance_variable_set("@_value_#{reflection.name}", value)
37
- }
31
+ read: lambda { |reflection, object|
32
+ value = object.instance_variable_get("@_value_#{reflection.name}")
33
+ JSON.parse(value) if value.present?
34
+ },
35
+ write: lambda { |reflection, object, value|
36
+ value = value.to_json if value
37
+ object.instance_variable_set("@_value_#{reflection.name}", value)
38
+ }
38
39
  end
39
40
  end
40
41
 
@@ -53,12 +54,15 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsOne do
53
54
 
54
55
  describe '#author=' do
55
56
  let(:author) { Author.new name: 'Author' }
57
+
56
58
  specify { expect { book.author = author }.to change { book.author }.from(nil).to(author) }
57
59
  specify { expect { book.author = 'string' }.to raise_error Granite::Form::AssociationTypeMismatch }
58
60
 
59
61
  context do
60
62
  let(:other) { Author.new name: 'Other' }
63
+
61
64
  before { book.author = other }
65
+
62
66
  specify { expect { book.author = author }.to change { book.author }.from(other).to(author) }
63
67
  specify { expect { book.author = nil }.to change { book.author }.from(other).to(nil) }
64
68
  end
@@ -66,6 +70,7 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsOne do
66
70
 
67
71
  describe '#build_author' do
68
72
  let(:author) { Author.new name: 'Author' }
73
+
69
74
  specify { expect(book.build_author(name: 'Author')).to eq(author) }
70
75
  specify { expect { book.build_author(name: 'Author') }.to change { book.author }.from(nil).to(author) }
71
76
  end
@@ -104,7 +109,12 @@ describe Granite::Form::Model::Associations::Reflections::EmbedsOne do
104
109
  specify { expect(Book.reflect_on_association(:author).klass).to eq(Book::Author) }
105
110
  specify { expect(Book.new.author).to be_nil }
106
111
  specify { expect(Book.new.tap { |b| b.build_author(name: 'Author') }.author).to be_a(Book::Author) }
107
- specify { expect(Book.new.tap { |b| b.build_author(name: 'Author') }.author).to have_attributes(name: 'Author', age: nil) }
112
+
113
+ specify do
114
+ book = Book.new
115
+ book.build_author(name: 'Author')
116
+ expect(book.author).to have_attributes(name: 'Author', age: nil)
117
+ end
108
118
  end
109
119
  end
110
120
  end
@@ -38,6 +38,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
38
38
  expect { book.creators << author }
39
39
  .to change { book.creators }.from([]).to([author])
40
40
  end
41
+
41
42
  specify do
42
43
  expect { book.creators << author }
43
44
  .to change { book.creator_ids }.from([]).to([author.id])
@@ -59,6 +60,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
59
60
  expect { book.author_names = [author.name] }
60
61
  .to change { book.authors }.from([]).to([author])
61
62
  end
63
+
62
64
  specify do
63
65
  expect { book.authors = [author] }
64
66
  .to change { book.author_names }.from([]).to([author.name])
@@ -79,6 +81,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
79
81
  expect { book.identify = [author.id] }
80
82
  .to change { book.authors }.from([]).to([author])
81
83
  end
84
+
82
85
  specify do
83
86
  expect { book.authors = [author] }
84
87
  .to change { book.identify }.from([]).to([author.id])
@@ -86,7 +89,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
86
89
  end
87
90
 
88
91
  describe ':default' do
89
- shared_examples_for :persisted_default do |default|
92
+ shared_examples_for 'persisted default' do |default|
90
93
  before do
91
94
  stub_model(:book) do
92
95
  include Granite::Form::Model::Associations
@@ -119,10 +122,10 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
119
122
  specify { expect { book.owner_ids = '' }.to change { book.owners }.from([author]).to([]) }
120
123
  end
121
124
 
122
- it_behaves_like :persisted_default, -> { authors.map(&:id) }
123
- it_behaves_like :persisted_default, -> { authors }
125
+ it_behaves_like 'persisted default', -> { authors.map(&:id) }
126
+ it_behaves_like 'persisted default', -> { authors }
124
127
 
125
- shared_examples_for :new_record_default do |default|
128
+ shared_examples_for 'new record default' do |default|
126
129
  before do
127
130
  stub_model(:book) do
128
131
  include Granite::Form::Model::Associations
@@ -139,7 +142,14 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
139
142
  specify { expect { book.owners = [other] }.to change { book.owner_ids }.from([nil]).to([other.id]) }
140
143
  specify { expect { book.owners = [other] }.to change { book.owners }.from([an_instance_of(Author)]).to([other]) }
141
144
  specify { expect { book.owner_ids = [other.id] }.to change { book.owner_ids }.from([nil]).to([other.id]) }
142
- specify { expect { book.owner_ids = [other.id] }.to change { book.owners }.from([an_instance_of(Author)]).to([other]) }
145
+
146
+ specify do
147
+ expect { book.owner_ids = [other.id] }
148
+ .to change { book.owners }
149
+ .from([an_instance_of(Author)])
150
+ .to([other])
151
+ end
152
+
143
153
  specify { expect { book.owners = [] }.to change { book.owner_ids }.from([nil]).to([]) }
144
154
  specify { expect { book.owners = [] }.to change { book.owners }.from([an_instance_of(Author)]).to([]) }
145
155
  specify { expect { book.owner_ids = [] }.not_to change { book.owner_ids }.from([nil]) }
@@ -154,12 +164,14 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
154
164
  specify { expect { book.owner_ids = '' }.to change { book.owners }.from([an_instance_of(Author)]).to([]) }
155
165
  end
156
166
 
157
- it_behaves_like :new_record_default, name: 'Author'
158
- it_behaves_like :new_record_default, -> { Author.new(name: 'Author') }
167
+ it_behaves_like 'new record default', name: 'Author'
168
+ it_behaves_like 'new record default', -> { Author.new(name: 'Author') }
159
169
  end
160
170
 
161
171
  describe 'Book.inspect' do
162
- specify { expect(Book.inspect).to eq('Book(authors: ReferencesMany(Author), title: String, author_ids: (reference))') }
172
+ specify do
173
+ expect(Book.inspect).to eq('Book(authors: ReferencesMany(Author), title: String, author_ids: (reference))')
174
+ end
163
175
  end
164
176
 
165
177
  describe '#scope' do
@@ -179,6 +191,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
179
191
  expect { book.authors = [author1, author2] }
180
192
  .to change { book.authors }.from([]).to([author1, author2])
181
193
  end
194
+
182
195
  specify do
183
196
  expect { book.authors = [author1, author2] }
184
197
  .to change { book.author_ids }.from([]).to([author1.id, author2.id])
@@ -188,6 +201,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
188
201
  expect { book.author_ids = [author1.id, author2.id] }
189
202
  .to change { book.authors }.from([]).to([author2])
190
203
  end
204
+
191
205
  specify do
192
206
  expect { book.author_ids = [author1.id, author2.id] }
193
207
  .to change { book.author_ids }.from([]).to([author2.id])
@@ -197,6 +211,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
197
211
  expect { book.authors = [author1, author2] }
198
212
  .to change { book.authors.reload }.from([]).to([author2])
199
213
  end
214
+
200
215
  specify do
201
216
  expect { book.authors = [author1, author2] }
202
217
  .to change {
@@ -228,14 +243,17 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
228
243
 
229
244
  describe '#reload' do
230
245
  before { book.authors << author.tap { |a| a.name = 'Don Juan' } }
246
+
231
247
  it { expect { book.authors.reload }.to change { book.authors.map(&:name) }.from(['Don Juan']).to(['Rick']) }
232
248
  end
233
249
 
234
250
  describe '#concat' do
235
251
  it { expect { book.authors.concat author }.to change { book.authors }.from([]).to([author]) }
236
252
  it { expect { book.authors << author << other }.to change { book.authors }.from([]).to([author, other]) }
253
+
237
254
  context 'no duplication' do
238
255
  before { book.authors << author }
256
+
239
257
  it { expect { book.authors.concat author }.not_to change { book.authors }.from([author]) }
240
258
  end
241
259
  end
@@ -249,8 +267,20 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
249
267
 
250
268
  describe '#author_ids' do
251
269
  it { expect(book_with_author.author_ids).to eq([author.id]) }
252
- xit { expect { book_with_author.author_ids << other.id }.to change { book_with_author.authors }.from([author]).to([author, other]) }
253
- it { expect { book_with_author.author_ids = [other.id] }.to change { book_with_author.authors }.from([author]).to([other]) }
270
+
271
+ xit do
272
+ expect { book_with_author.author_ids << other.id }
273
+ .to change { book_with_author.authors }
274
+ .from([author])
275
+ .to([author, other])
276
+ end
277
+
278
+ it {
279
+ expect { book_with_author.author_ids = [other.id] }
280
+ .to change { book_with_author.authors }
281
+ .from([author])
282
+ .to([other])
283
+ }
254
284
  end
255
285
 
256
286
  describe '#authors=' do
@@ -259,6 +289,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
259
289
 
260
290
  context do
261
291
  before { book.authors = [other] }
292
+
262
293
  specify { expect { book.authors = [author] }.to change { book.authors }.from([other]).to([author]) }
263
294
  specify { expect { book.authors = [author] }.to change { book.author_ids }.from([other.id]).to([author.id]) }
264
295
  specify { expect { book.authors = [] }.to change { book.authors }.from([other]).to([]) }
@@ -267,16 +298,19 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
267
298
 
268
299
  context 'model not persisted' do
269
300
  let(:author) { Author.new }
301
+
270
302
  specify { expect { book.authors = [author, other] }.to change { book.authors }.from([]).to([author, other]) }
271
303
  specify { expect { book.authors = [author, other] }.to change { book.author_ids }.from([]).to([nil, other.id]) }
272
304
 
273
305
  context do
274
306
  before { book.authors = [author, other] }
307
+
275
308
  specify do
276
309
  expect { author.save! }.to change { book.author_ids }.from([nil, other.id])
277
- .to(match([be_a(Integer), other.id]))
310
+ .to(match([be_a(Integer), other.id]))
278
311
  end
279
- specify { expect { author.save! }.not_to change { book.authors } }
312
+
313
+ specify { expect { author.save! }.not_to(change { book.authors }) }
280
314
  end
281
315
  end
282
316
  end
@@ -289,12 +323,30 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesMany do
289
323
  specify { expect { book.author_ids = [author.id.next.to_s] }.not_to change { book.author_ids }.from([]) }
290
324
  specify { expect { book.author_ids = [author.id.next.to_s] }.not_to change { book.authors }.from([]) }
291
325
 
292
- specify { expect { book.author_ids = [author.id.next.to_s, author.id] }.to change { book.author_ids }.from([]).to([author.id]) }
293
- specify { expect { book.author_ids = [author.id.next.to_s, author.id] }.to change { book.authors }.from([]).to([author]) }
326
+ specify do
327
+ expect { book.author_ids = [author.id.next.to_s, author.id] }
328
+ .to change { book.author_ids }
329
+ .from([])
330
+ .to([author.id])
331
+ end
332
+
333
+ specify do
334
+ expect { book.author_ids = [author.id.next.to_s, author.id] }
335
+ .to change { book.authors }
336
+ .from([])
337
+ .to([author])
338
+ end
294
339
 
295
340
  context do
296
341
  before { book.authors = [other] }
297
- specify { expect { book.author_ids = [author.id] }.to change { book.author_ids }.from([other.id]).to([author.id]) }
342
+
343
+ specify do
344
+ expect { book.author_ids = [author.id] }
345
+ .to change { book.author_ids }
346
+ .from([other.id])
347
+ .to([author.id])
348
+ end
349
+
298
350
  specify { expect { book.author_ids = [author.id] }.to change { book.authors }.from([other]).to([author]) }
299
351
  specify { expect { book.author_ids = [] }.to change { book.author_ids }.from([other.id]).to([]) }
300
352
  specify { expect { book.author_ids = [] }.to change { book.authors }.from([other]).to([]) }
@@ -14,6 +14,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
14
14
  references_one :author
15
15
  end
16
16
  end
17
+
17
18
  let(:book) { Book.new }
18
19
 
19
20
  specify { expect(book.author).to be_nil }
@@ -27,12 +28,14 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
27
28
  references_one :creator, class_name: 'Author'
28
29
  end
29
30
  end
31
+
30
32
  let(:author) { Author.create!(name: 'Rick') }
31
33
 
32
34
  specify do
33
35
  expect { book.creator = author }
34
36
  .to change { book.creator }.from(nil).to(author)
35
37
  end
38
+
36
39
  specify do
37
40
  expect { book.creator = author }
38
41
  .to change { book.creator_id }.from(nil).to(author.id)
@@ -54,6 +57,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
54
57
  expect { book.author_name = author.name }
55
58
  .to change { book.author }.from(nil).to(author)
56
59
  end
60
+
57
61
  specify do
58
62
  expect { book.author = author }
59
63
  .to change { book.author_name }.from(nil).to(author.name)
@@ -74,6 +78,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
74
78
  expect { book.identify = author.id }
75
79
  .to change { book.author }.from(nil).to(author)
76
80
  end
81
+
77
82
  specify do
78
83
  expect { book.author = author }
79
84
  .to change { book.identify }.from(nil).to(author.id)
@@ -81,7 +86,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
81
86
  end
82
87
 
83
88
  describe ':default' do
84
- shared_examples_for :persisted_default do |default|
89
+ shared_examples_for 'persisted default' do |default|
85
90
  before do
86
91
  stub_model(:book) do
87
92
  include Granite::Form::Model::Associations
@@ -108,10 +113,10 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
108
113
  specify { expect { book.owner_id = '' }.to change { book.owner }.from(author).to(nil) }
109
114
  end
110
115
 
111
- it_behaves_like :persisted_default, -> { author.id }
112
- it_behaves_like :persisted_default, -> { author }
116
+ it_behaves_like 'persisted default', -> { author.id }
117
+ it_behaves_like 'persisted default', -> { author }
113
118
 
114
- shared_examples_for :new_record_default do |default|
119
+ shared_examples_for 'new record default' do |default|
115
120
  before do
116
121
  stub_model(:book) do
117
122
  include Granite::Form::Model::Associations
@@ -137,8 +142,8 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
137
142
  specify { expect { book.owner_id = '' }.to change { book.owner }.from(instance_of(Author)).to(nil) }
138
143
  end
139
144
 
140
- it_behaves_like :new_record_default, name: 'Author'
141
- it_behaves_like :new_record_default, -> { Author.new(name: 'Author') }
145
+ it_behaves_like 'new record default', name: 'Author'
146
+ it_behaves_like 'new record default', -> { Author.new(name: 'Author') }
142
147
  end
143
148
 
144
149
  describe 'Book.inspect' do
@@ -160,8 +165,9 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
160
165
 
161
166
  specify do
162
167
  expect { book.author_id = author1.id }
163
- .not_to change { book.author }
168
+ .not_to(change { book.author })
164
169
  end
170
+
165
171
  specify do
166
172
  expect { book.author_id = author2.id }
167
173
  .to change { book.author }.from(nil).to(author2)
@@ -171,6 +177,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
171
177
  expect { book.author = author1 }
172
178
  .to change { book.author_id }.from(nil).to(author1.id)
173
179
  end
180
+
174
181
  specify do
175
182
  expect { book.author = author2 }
176
183
  .to change { book.author_id }.from(nil).to(author2.id)
@@ -183,6 +190,7 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
183
190
  book.author_id
184
191
  }.from(nil).to(author1.id)
185
192
  end
193
+
186
194
  specify do
187
195
  expect { book.author = author2 }
188
196
  .to change {
@@ -193,11 +201,12 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
193
201
 
194
202
  specify do
195
203
  expect { book.author = author1 }
196
- .not_to change {
204
+ .not_to(change do
197
205
  book.association(:author).reload
198
206
  book.author
199
- }
207
+ end)
200
208
  end
209
+
201
210
  specify do
202
211
  expect { book.author = author2 }
203
212
  .to change {
@@ -220,12 +229,15 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
220
229
 
221
230
  describe '#author=' do
222
231
  let(:author) { Author.create! name: 'Author' }
232
+
223
233
  specify { expect { book.author = author }.to change { book.author }.from(nil).to(author) }
224
234
  specify { expect { book.author = 'string' }.to raise_error Granite::Form::AssociationTypeMismatch }
225
235
 
226
236
  context do
227
237
  let(:other) { Author.create! name: 'Other' }
238
+
228
239
  before { book.author = other }
240
+
229
241
  specify { expect { book.author = author }.to change { book.author }.from(other).to(author) }
230
242
  specify { expect { book.author = author }.to change { book.author_id }.from(other.id).to(author.id) }
231
243
  specify { expect { book.author = nil }.to change { book.author }.from(other).to(nil) }
@@ -234,29 +246,40 @@ describe Granite::Form::Model::Associations::Reflections::ReferencesOne do
234
246
 
235
247
  context 'model not persisted' do
236
248
  let(:author) { Author.new }
249
+
237
250
  specify { expect { book.author = author }.to change { book.author }.from(nil).to(author) }
238
251
  specify { expect { book.author = author }.not_to change { book.author_id }.from(nil) }
239
252
 
240
253
  context do
241
254
  before { book.author = author }
255
+
242
256
  specify { expect { author.save! }.to change { book.author_id }.from(nil).to(be_a(Integer)) }
243
- specify { expect { author.save! }.not_to change { book.author } }
257
+ specify { expect { author.save! }.not_to(change { book.author }) }
244
258
  end
245
259
  end
246
260
  end
247
261
 
248
262
  describe '#author_id=' do
249
263
  let(:author) { Author.create!(name: 'Author') }
264
+
250
265
  specify { expect { book.author_id = author.id }.to change { book.author_id }.from(nil).to(author.id) }
251
266
  specify { expect { book.author_id = author.id }.to change { book.author }.from(nil).to(author) }
252
267
  specify { expect { book.author_id = author }.to change { book.author }.from(nil).to(author) }
253
268
 
254
- specify { expect { book.author_id = author.id.next.to_s }.to change { book.author_id }.from(nil).to(author.id.next) }
269
+ specify do
270
+ expect { book.author_id = author.id.next.to_s }
271
+ .to change { book.author_id }
272
+ .from(nil)
273
+ .to(author.id.next)
274
+ end
275
+
255
276
  specify { expect { book.author_id = author.id.next.to_s }.not_to change { book.author }.from(nil) }
256
277
 
257
278
  context do
258
279
  let(:other) { Author.create!(name: 'Other') }
280
+
259
281
  before { book.author = other }
282
+
260
283
  specify { expect { book.author_id = author.id }.to change { book.author_id }.from(other.id).to(author.id) }
261
284
  specify { expect { book.author_id = author.id }.to change { book.author }.from(other).to(author) }
262
285
  specify { expect { book.author_id = nil }.to change { book.author_id }.from(other.id).to(nil) }
@@ -38,16 +38,18 @@ describe Granite::Form::Model::Associations::Validations do
38
38
  let(:project) { Project.new title: 'Project' }
39
39
  let(:projects) { [project] }
40
40
  let(:user) { User.new(login: 'Login', profile: profile, projects: projects) }
41
- let(:author_attributes) { {name: 'Author'} }
41
+ let(:author_attributes) { { name: 'Author' } }
42
+
42
43
  before { project.build_author(author_attributes) }
43
44
 
44
45
  specify { expect(user.validate).to eq(true) }
45
- specify { expect { user.validate }.not_to change { user.errors.messages } }
46
+ specify { expect { user.validate }.not_to(change { user.errors.messages }) }
46
47
 
47
48
  context do
48
49
  let(:author_attributes) { {} }
49
50
 
50
51
  specify { expect(user.validate).to eq(false) }
52
+
51
53
  specify do
52
54
  expect { user.validate }.to change { user.errors.messages }
53
55
  .to('projects.0.author.name': ["can't be blank"])
@@ -58,13 +60,14 @@ describe Granite::Form::Model::Associations::Validations do
58
60
  let(:profile) { Profile.new }
59
61
 
60
62
  specify { expect(user.validate).to eq(true) }
61
- specify { expect { user.validate }.not_to change { user.errors.messages } }
63
+ specify { expect { user.validate }.not_to(change { user.errors.messages }) }
62
64
  end
63
65
 
64
66
  context do
65
67
  let(:projects) { [project, Project.new] }
66
68
 
67
69
  specify { expect(user.validate).to eq(false) }
70
+
68
71
  specify do
69
72
  expect { user.validate }.to change { user.errors.messages }
70
73
  .to('projects.1.title': ["can't be blank"])
@@ -77,7 +80,8 @@ describe Granite::Form::Model::Associations::Validations do
77
80
  let(:project) { Project.new title: 'Project' }
78
81
  let(:projects) { [project] }
79
82
  let(:user) { User.new(login: 'Login', profile: profile, projects: projects) }
80
- let(:author_attributes) { {name: 'Author'} }
83
+ let(:author_attributes) { { name: 'Author' } }
84
+
81
85
  before { project.build_author(author_attributes) }
82
86
 
83
87
  specify { expect(user.validate_ancestry).to eq(true) }
@@ -85,14 +89,16 @@ describe Granite::Form::Model::Associations::Validations do
85
89
  specify { expect { user.validate_ancestry! }.not_to raise_error }
86
90
  specify { expect(user.valid_ancestry?).to eq(true) }
87
91
  specify { expect(user.invalid_ancestry?).to eq(false) }
88
- specify { expect { user.validate_ancestry }.not_to change { user.errors.messages } }
92
+ specify { expect { user.validate_ancestry }.not_to(change { user.errors.messages }) }
89
93
 
90
94
  context do
91
95
  let(:author_attributes) { {} }
96
+
92
97
  specify { expect(user.validate_ancestry).to eq(false) }
93
98
  specify { expect { user.validate_ancestry! }.to raise_error Granite::Form::ValidationError }
94
99
  specify { expect(user.valid_ancestry?).to eq(false) }
95
100
  specify { expect(user.invalid_ancestry?).to eq(true) }
101
+
96
102
  specify do
97
103
  expect { user.validate_ancestry }.to change { user.errors.messages }
98
104
  .to('projects.0.author.name': ["can't be blank"])
@@ -101,10 +107,12 @@ describe Granite::Form::Model::Associations::Validations do
101
107
 
102
108
  context do
103
109
  let(:profile) { Profile.new }
110
+
104
111
  specify { expect(user.validate_ancestry).to eq(false) }
105
112
  specify { expect { user.validate_ancestry! }.to raise_error Granite::Form::ValidationError }
106
113
  specify { expect(user.valid_ancestry?).to eq(false) }
107
114
  specify { expect(user.invalid_ancestry?).to eq(true) }
115
+
108
116
  specify do
109
117
  expect { user.validate_ancestry }.to change { user.errors.messages }
110
118
  .to('profile.first_name': ["can't be blank"])
@@ -113,10 +121,12 @@ describe Granite::Form::Model::Associations::Validations do
113
121
 
114
122
  context do
115
123
  let(:projects) { [project, Project.new] }
124
+
116
125
  specify { expect(user.validate_ancestry).to eq(false) }
117
126
  specify { expect { user.validate_ancestry! }.to raise_error Granite::Form::ValidationError }
118
127
  specify { expect(user.valid_ancestry?).to eq(false) }
119
128
  specify { expect(user.invalid_ancestry?).to eq(true) }
129
+
120
130
  specify do
121
131
  expect { user.validate_ancestry }.to change { user.errors.messages }
122
132
  .to('projects.1.title': ["can't be blank"])
@@ -124,6 +134,7 @@ describe Granite::Form::Model::Associations::Validations do
124
134
 
125
135
  context do
126
136
  before { user.update(login: '') }
137
+
127
138
  specify do
128
139
  expect { user.validate_ancestry }.to change { user.errors.messages }
129
140
  .to('projects.1.title': ["can't be blank"], login: ["can't be blank"])