granite-form 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +26 -48
  3. data/.rubocop_todo.yml +304 -27
  4. data/CHANGELOG.md +7 -2
  5. data/granite-form.gemspec +2 -1
  6. data/lib/granite/form/active_record/associations.rb +4 -3
  7. data/lib/granite/form/config.rb +1 -1
  8. data/lib/granite/form/errors.rb +34 -32
  9. data/lib/granite/form/extensions.rb +2 -1
  10. data/lib/granite/form/model/associations/base.rb +6 -2
  11. data/lib/granite/form/model/associations/collection/embedded.rb +1 -1
  12. data/lib/granite/form/model/associations/collection/proxy.rb +3 -3
  13. data/lib/granite/form/model/associations/embeds_any.rb +1 -1
  14. data/lib/granite/form/model/associations/embeds_many.rb +15 -11
  15. data/lib/granite/form/model/associations/embeds_one.rb +9 -8
  16. data/lib/granite/form/model/associations/nested_attributes.rb +60 -32
  17. data/lib/granite/form/model/associations/persistence_adapters/active_record/referenced_proxy.rb +2 -1
  18. data/lib/granite/form/model/associations/persistence_adapters/active_record.rb +7 -6
  19. data/lib/granite/form/model/associations/persistence_adapters/base.rb +8 -4
  20. data/lib/granite/form/model/associations/references_any.rb +1 -1
  21. data/lib/granite/form/model/associations/references_many.rb +3 -2
  22. data/lib/granite/form/model/associations/references_one.rb +1 -1
  23. data/lib/granite/form/model/associations/reflections/base.rb +3 -2
  24. data/lib/granite/form/model/associations/reflections/embeds_any.rb +4 -4
  25. data/lib/granite/form/model/associations/reflections/embeds_many.rb +4 -1
  26. data/lib/granite/form/model/associations/reflections/embeds_one.rb +4 -1
  27. data/lib/granite/form/model/associations/reflections/references_any.rb +6 -6
  28. data/lib/granite/form/model/associations/reflections/references_many.rb +1 -1
  29. data/lib/granite/form/model/associations/reflections/references_one.rb +1 -1
  30. data/lib/granite/form/model/associations/validations.rb +6 -6
  31. data/lib/granite/form/model/associations.rb +6 -4
  32. data/lib/granite/form/model/attributes/attribute.rb +1 -0
  33. data/lib/granite/form/model/attributes/base.rb +9 -7
  34. data/lib/granite/form/model/attributes/reference_one.rb +1 -1
  35. data/lib/granite/form/model/attributes/reflections/base/build_type_definition.rb +2 -1
  36. data/lib/granite/form/model/attributes/reflections/represents/build_type_definition.rb +2 -2
  37. data/lib/granite/form/model/attributes/represents.rb +1 -1
  38. data/lib/granite/form/model/attributes.rb +21 -13
  39. data/lib/granite/form/model/conventions.rb +1 -1
  40. data/lib/granite/form/model/persistence.rb +1 -1
  41. data/lib/granite/form/model/primary.rb +1 -1
  42. data/lib/granite/form/model/representation.rb +4 -4
  43. data/lib/granite/form/model/scopes.rb +5 -5
  44. data/lib/granite/form/model/validations.rb +4 -3
  45. data/lib/granite/form/types/active_support/time_zone.rb +1 -1
  46. data/lib/granite/form/types/array.rb +1 -1
  47. data/lib/granite/form/types/big_decimal.rb +1 -1
  48. data/lib/granite/form/types/boolean.rb +1 -1
  49. data/lib/granite/form/types/date.rb +1 -1
  50. data/lib/granite/form/types/date_time.rb +1 -1
  51. data/lib/granite/form/types/dictionary.rb +1 -1
  52. data/lib/granite/form/types/float.rb +1 -1
  53. data/lib/granite/form/types/has_subtype.rb +1 -0
  54. data/lib/granite/form/types/hash_with_action_controller_parameters.rb +2 -2
  55. data/lib/granite/form/types/integer.rb +1 -1
  56. data/lib/granite/form/types/object.rb +2 -1
  57. data/lib/granite/form/types/string.rb +1 -1
  58. data/lib/granite/form/types/time.rb +1 -1
  59. data/lib/granite/form/types/uuid.rb +1 -1
  60. data/lib/granite/form/util.rb +1 -1
  61. data/lib/granite/form/version.rb +1 -1
  62. data/spec/granite/form/active_record/associations_spec.rb +35 -13
  63. data/spec/granite/form/config_spec.rb +8 -4
  64. data/spec/granite/form/model/associations/embeds_many_spec.rb +99 -51
  65. data/spec/granite/form/model/associations/embeds_one_spec.rb +48 -25
  66. data/spec/granite/form/model/associations/persistence_adapters/active_record_spec.rb +12 -7
  67. data/spec/granite/form/model/associations/references_many_spec.rb +51 -10
  68. data/spec/granite/form/model/associations/references_one_spec.rb +17 -6
  69. data/spec/granite/form/model/associations/reflections/embeds_many_spec.rb +51 -16
  70. data/spec/granite/form/model/associations/reflections/embeds_one_spec.rb +19 -9
  71. data/spec/granite/form/model/associations/reflections/references_many_spec.rb +67 -15
  72. data/spec/granite/form/model/associations/reflections/references_one_spec.rb +34 -11
  73. data/spec/granite/form/model/associations/validations_spec.rb +16 -5
  74. data/spec/granite/form/model/associations_spec.rb +28 -9
  75. data/spec/granite/form/model/attributes/attribute_spec.rb +33 -11
  76. data/spec/granite/form/model/attributes/base_spec.rb +9 -3
  77. data/spec/granite/form/model/attributes/reflections/attribute_spec.rb +1 -0
  78. data/spec/granite/form/model/attributes/reflections/base_spec.rb +1 -0
  79. data/spec/granite/form/model/attributes/reflections/represents/build_type_definition_spec.rb +3 -1
  80. data/spec/granite/form/model/attributes/reflections/represents_spec.rb +2 -2
  81. data/spec/granite/form/model/attributes/represents_spec.rb +2 -2
  82. data/spec/granite/form/model/attributes_spec.rb +76 -36
  83. data/spec/granite/form/model/dirty_spec.rb +3 -0
  84. data/spec/granite/form/model/persistence_spec.rb +15 -5
  85. data/spec/granite/form/model/primary_spec.rb +17 -2
  86. data/spec/granite/form/model/representation_spec.rb +13 -3
  87. data/spec/granite/form/model/scopes_spec.rb +8 -3
  88. data/spec/granite/form/model/validations/associated_spec.rb +20 -6
  89. data/spec/granite/form/model/validations/nested_spec.rb +30 -14
  90. data/spec/granite/form/model/validations_spec.rb +1 -1
  91. data/spec/granite/form/model_spec.rb +1 -0
  92. data/spec/granite/form/types/collection_spec.rb +2 -1
  93. data/spec/granite/form/types/date_spec.rb +1 -1
  94. data/spec/granite/form/types/date_time_spec.rb +0 -2
  95. data/spec/granite/form/types/dictionary_spec.rb +1 -0
  96. data/spec/granite/form/types/has_subtype_spec.rb +6 -1
  97. data/spec/granite/form/types/hash_with_action_controller_parameters_spec.rb +1 -1
  98. data/spec/granite/form/types/object_spec.rb +2 -0
  99. data/spec/granite/form/types/time_spec.rb +0 -2
  100. data/spec/granite/form/util_spec.rb +6 -3
  101. data/spec/support/active_record.rb +13 -0
  102. data/spec/support/shared/nested_attribute_examples.rb +110 -54
  103. metadata +23 -9
@@ -34,13 +34,16 @@ describe Granite::Form::Model::Validations::NestedValidator do
34
34
  end
35
35
 
36
36
  context do
37
- subject(:instance) { Main.instantiate name: 'hello', validated_one: {name: 'name'} }
37
+ subject(:instance) { Main.instantiate name: 'hello', validated_one: { name: 'name' } }
38
+
38
39
  it { is_expected.to be_valid }
39
40
  end
40
41
 
41
42
  context do
42
43
  subject(:instance) { Main.instantiate name: 'hello', validated_one: {} }
44
+
43
45
  it { is_expected.not_to be_valid }
46
+
44
47
  specify do
45
48
  expect { instance.validate }.to change { instance.errors.messages }
46
49
  .to('validated_one.name': ["can't be blank"])
@@ -48,23 +51,28 @@ describe Granite::Form::Model::Validations::NestedValidator do
48
51
  end
49
52
 
50
53
  context do
51
- subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {name: 'name'} }
54
+ subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: { name: 'name' } }
55
+
52
56
  it { is_expected.to be_valid }
53
57
  end
54
58
 
55
59
  context do
56
60
  subject(:instance) { Main.instantiate name: 'hello', unvalidated_one: {} }
61
+
57
62
  it { is_expected.to be_valid }
58
63
  end
59
64
 
60
65
  context do
61
- subject(:instance) { Main.instantiate name: 'hello', validated_many: [{name: 'name'}] }
66
+ subject(:instance) { Main.instantiate name: 'hello', validated_many: [{ name: 'name' }] }
67
+
62
68
  it { is_expected.to be_valid }
63
69
  end
64
70
 
65
71
  context do
66
72
  subject(:instance) { Main.instantiate name: 'hello', validated_many: [{}] }
73
+
67
74
  it { is_expected.not_to be_valid }
75
+
68
76
  specify do
69
77
  expect { instance.validate }.to change { instance.errors.messages }
70
78
  .to('validated_many.0.name': ["can't be blank"])
@@ -72,18 +80,22 @@ describe Granite::Form::Model::Validations::NestedValidator do
72
80
  end
73
81
 
74
82
  context do
75
- subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{name: 'name'}] }
83
+ subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{ name: 'name' }] }
84
+
76
85
  it { is_expected.to be_valid }
77
86
  end
78
87
 
79
88
  context do
80
89
  subject(:instance) { Main.instantiate name: 'hello', unvalidated_many: [{}] }
90
+
81
91
  it { is_expected.to be_valid }
82
92
  end
83
93
 
84
94
  context do
85
- subject(:instance) { Main.instantiate name: 'hello', validated_many: [{name: 'name'}], validated_one: {} }
95
+ subject(:instance) { Main.instantiate name: 'hello', validated_many: [{ name: 'name' }], validated_one: {} }
96
+
86
97
  it { is_expected.not_to be_valid }
98
+
87
99
  specify do
88
100
  expect { instance.validate }.to change { instance.errors.messages }
89
101
  .to('validated_one.name': ["can't be blank"])
@@ -91,26 +103,30 @@ describe Granite::Form::Model::Validations::NestedValidator do
91
103
  end
92
104
 
93
105
  context 'accepts nested attributes for one' do
106
+ subject(:instance) { Main.instantiate name: 'hello', validated_one: { id: 1, name: 'name' } }
107
+
94
108
  before { Main.accepts_nested_attributes_for :validated_one, allow_destroy: true }
95
- subject(:instance) { Main.instantiate name: 'hello', validated_one: {id: 1, name: 'name'} }
96
109
 
97
110
  specify do
98
- instance.validated_one_attributes = {id: 1, name: '', _destroy: true}
99
- is_expected.to be_valid
111
+ instance.validated_one_attributes = { id: 1, name: '', _destroy: true }
112
+ expect(subject).to be_valid
100
113
  end
101
114
  end
102
115
 
103
116
  context 'accepts nested attributes for many' do
117
+ subject(:instance) { Main.instantiate name: 'hello', validated_many: [{ id: 1, name: 'name' }] }
118
+
104
119
  before { Main.accepts_nested_attributes_for :validated_many, allow_destroy: true }
105
- subject(:instance) { Main.instantiate name: 'hello', validated_many: [{id: 1, name: 'name'}] }
106
120
 
107
121
  specify do
108
- instance.validated_many_attributes = [{id: 1, name: '', _destroy: true}]
109
- is_expected.to be_valid
122
+ instance.validated_many_attributes = [{ id: 1, name: '', _destroy: true }]
123
+ expect(subject).to be_valid
110
124
  end
111
125
  end
112
126
 
113
127
  context 'object field is invalid and referenced object does not include AutosaveAssociation' do
128
+ subject(:instance) { Main.instantiate name: 'hello', object: object }
129
+
114
130
  before do
115
131
  stub_model(:validated_object) do
116
132
  attribute :title, String
@@ -125,8 +141,6 @@ describe Granite::Form::Model::Validations::NestedValidator do
125
141
  end
126
142
  end
127
143
 
128
- subject(:instance) { Main.instantiate name: 'hello', object: object }
129
-
130
144
  context 'nested object is valid' do
131
145
  let(:object) { ValidatedObject.new(title: 'Mr.') }
132
146
 
@@ -190,8 +204,10 @@ describe Granite::Form::Model::Validations::NestedValidator do
190
204
  end
191
205
 
192
206
  context do
193
- subject(:instance) { Main.instantiate name: 'hello', validated_many: [{}], validated_one: {name: 'name'} }
207
+ subject(:instance) { Main.instantiate name: 'hello', validated_many: [{}], validated_one: { name: 'name' } }
208
+
194
209
  it { is_expected.not_to be_valid }
210
+
195
211
  specify do
196
212
  expect { instance.validate }.to change { instance.errors.messages }
197
213
  .to('validated_many.0.name': ["can't be blank"])
@@ -29,7 +29,7 @@ describe Granite::Form::Model::Validations do
29
29
  end
30
30
 
31
31
  context 'when attribute has different validations' do
32
- let(:add_validations) { model.validates :name, length: {maximum: 100} }
32
+ let(:add_validations) { model.validates :name, length: { maximum: 100 } }
33
33
 
34
34
  it { is_expected.to be_falsey }
35
35
  end
@@ -2,6 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Granite::Form::Model do
4
4
  let(:model) { stub_model }
5
+
5
6
  specify { expect { model.blablabla }.to raise_error NoMethodError }
6
7
 
7
8
  context 'Fault tolerance' do
@@ -2,6 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe Granite::Form::Types::Collection do
4
4
  subject(:type) { described_class.new(subtype_definition) }
5
+
5
6
  let(:element_type) { Dummy }
6
7
  let(:subtype_definition) { Granite::Form::Types::Object.new(element_type, reflection, nil) }
7
8
  let(:reflection) { Granite::Form::Model::Attributes::Reflections::Base.new(:field) }
@@ -16,7 +17,7 @@ RSpec.describe Granite::Form::Types::Collection do
16
17
  context 'with Hash collection' do
17
18
  let(:element_type) { Hash }
18
19
 
19
- specify { expect(subject.prepare([{key: 'value'}])).to eq([{key: 'value'}]) }
20
+ specify { expect(subject.prepare([{ key: 'value' }])).to eq([{ key: 'value' }]) }
20
21
  end
21
22
  end
22
23
  end
@@ -11,7 +11,7 @@ RSpec.describe Granite::Form::Types::Date do
11
11
  specify { expect(typecast('2013-06-13')).to eq(date) }
12
12
  specify { expect(typecast('2013-55-55')).to be_nil }
13
13
  specify { expect(typecast('blablabla')).to be_nil }
14
- specify { expect(typecast(DateTime.new(2013, 6, 13, 23, 13))).to eq(date) } # rubocop:disable Style/DateTime
14
+ specify { expect(typecast(DateTime.new(2013, 6, 13, 23, 13))).to eq(date) }
15
15
  specify { expect(typecast(Time.new(2013, 6, 13, 23, 13))).to eq(date) }
16
16
  specify { expect(typecast(Date.new(2013, 6, 13))).to eq(date) }
17
17
  end
@@ -3,7 +3,6 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Granite::Form::Types::DateTime do
6
- # rubocop:disable Style/DateTime
7
6
  describe 'typecasting' do
8
7
  include_context 'type setup', 'DateTime'
9
8
  let(:datetime) { DateTime.new(2013, 6, 13, 23, 13) }
@@ -16,5 +15,4 @@ RSpec.describe Granite::Form::Types::DateTime do
16
15
  specify { expect(typecast(Time.utc(2013, 6, 13, 23, 13).utc)).to eq(datetime) }
17
16
  specify { expect(typecast(DateTime.new(2013, 6, 13, 23, 13))).to eq(datetime) }
18
17
  end
19
- # rubocop:enable Style/DateTime
20
18
  end
@@ -4,6 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe Granite::Form::Types::Dictionary do
6
6
  subject(:type) { described_class.new(subtype_definition) }
7
+
7
8
  let(:element_type) { Dummy }
8
9
  let(:subtype_definition) { Granite::Form::Types::Object.new(element_type, reflection, nil) }
9
10
  let(:reflection) { build_reflection }
@@ -4,6 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe Granite::Form::Types::HasSubtype do
6
6
  subject(:type) { described_class.new(subtype_definition) }
7
+
7
8
  let(:subtype_definition) { Granite::Form::Types::Object.new(Dummy, reflection, nil) }
8
9
  let(:reflection) { Granite::Form::Model::Attributes::Reflections::Base.new(:field) }
9
10
  let(:dummy_object) { Dummy.new }
@@ -12,9 +13,13 @@ describe Granite::Form::Types::HasSubtype do
12
13
 
13
14
  describe '#build_duplicate' do
14
15
  subject { type.build_duplicate(new_reflection, new_model) }
16
+
15
17
  let(:new_model) { double('new_model') }
16
18
  let(:new_reflection) { double('new_reflection') }
17
19
 
18
- it { is_expected.to have_attributes(subtype_definition: have_attributes(type: Dummy, reflection: new_reflection, owner: new_model)) }
20
+ it {
21
+ expect(subject).to have_attributes(subtype_definition: have_attributes(type: Dummy, reflection: new_reflection,
22
+ owner: new_model))
23
+ }
19
24
  end
20
25
  end
@@ -11,7 +11,7 @@ RSpec.describe Granite::Form::Types::HashWithActionControllerParameters do
11
11
  Class.new(ActionController::Base)
12
12
  end
13
13
 
14
- let(:to_h) { {'x' => {'foo' => 'bar'}, 'y' => 2} }
14
+ let(:to_h) { { 'x' => { 'foo' => 'bar' }, 'y' => 2 } }
15
15
  let(:parameters) { ActionController::Parameters.new(to_h) }
16
16
 
17
17
  specify { expect(typecast(nil)).to be_nil }
@@ -4,6 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  RSpec.describe Granite::Form::Types::Object do
6
6
  subject(:type) { build_type(reflection: reflection) }
7
+
7
8
  let(:model) { Model.new }
8
9
  let(:reflection) { build_reflection }
9
10
 
@@ -25,6 +26,7 @@ RSpec.describe Granite::Form::Types::Object do
25
26
 
26
27
  describe '#build_duplicate' do
27
28
  subject { type.build_duplicate(new_reflection, new_model) }
29
+
28
30
  let(:new_model) { double('new_model') }
29
31
  let(:new_reflection) { Granite::Form::Model::Attributes::Reflections::Base.new(:new_field) }
30
32
 
@@ -3,7 +3,6 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Granite::Form::Types::Time do
6
- # rubocop:disable Style/DateTime
7
6
  describe 'typecasting' do
8
7
  include_context 'type setup', 'Time'
9
8
 
@@ -27,5 +26,4 @@ RSpec.describe Granite::Form::Types::Time do
27
26
  specify { expect(typecast(Time.new(2013, 6, 13, 23, 13))).to eq(Time.new(2013, 6, 13, 23, 13)) }
28
27
  end
29
28
  end
30
- # rubocop:enable Style/DateTime
31
29
  end
@@ -21,6 +21,7 @@ RSpec.describe Granite::Form::Util do
21
21
 
22
22
  describe '#evaluate' do
23
23
  subject { dummy.evaluate(target) }
24
+
24
25
  let(:target) { 'Peter' }
25
26
 
26
27
  it { is_expected.to eq('Peter') }
@@ -56,6 +57,7 @@ RSpec.describe Granite::Form::Util do
56
57
 
57
58
  describe '#evaluate_if_proc' do
58
59
  subject { dummy.evaluate(target) }
60
+
59
61
  let(:target) { 'Peter' }
60
62
 
61
63
  it { is_expected.to eq('Peter') }
@@ -77,7 +79,8 @@ RSpec.describe Granite::Form::Util do
77
79
 
78
80
  describe '#conditions_satisfied?' do
79
81
  subject { dummy.conditions_satisfied?(**conditions) }
80
- let(:conditions) { {if: -> { name == 'John' }} }
82
+
83
+ let(:conditions) { { if: -> { name == 'John' } } }
81
84
 
82
85
  it { is_expected.to be_truthy }
83
86
 
@@ -88,7 +91,7 @@ RSpec.describe Granite::Form::Util do
88
91
  end
89
92
 
90
93
  context 'when unless condition is passed' do
91
- let(:conditions) { {unless: :name} }
94
+ let(:conditions) { { unless: :name } }
92
95
 
93
96
  it { is_expected.to be_falsey }
94
97
  end
@@ -100,7 +103,7 @@ RSpec.describe Granite::Form::Util do
100
103
  end
101
104
 
102
105
  context 'when both if & unless are passed' do
103
- let(:conditions) { {if: :name, unless: :name} }
106
+ let(:conditions) { { if: :name, unless: :name } }
104
107
 
105
108
  it { expect { subject }.to raise_error(ArgumentError) }
106
109
  end
@@ -20,4 +20,17 @@ ActiveRecord::Schema.define do
20
20
  t.column :related_ids, :integer, array: true
21
21
  t.column :data, :text
22
22
  end
23
+
24
+ if ActiveModel.version >= Gem::Version.new('7.0.0')
25
+ create_enum 'foo', %w[foo bar baz]
26
+
27
+ create_table :foo_containers, force: :cascade do |t|
28
+ t.enum :foos, enum_type: 'foo', array: true
29
+ end
30
+ end
31
+ end
32
+
33
+ if ActiveModel.version >= Gem::Version.new('7.0.0')
34
+ class FooContainer < ActiveRecord::Base
35
+ end
23
36
  end
@@ -23,18 +23,34 @@ shared_examples 'nested attributes' do
23
23
  let(:user) { User.new }
24
24
 
25
25
  specify { expect { user.profile_attributes = {} }.to change { user.profile }.to(an_instance_of(Profile)) }
26
- specify { expect { user.profile_attributes = {first_name: 'User'} }.to change { user.profile.try(:first_name) }.to('User') }
27
- specify { expect { user.profile_attributes = {identifier: 42, first_name: 'User'} }.to raise_error Granite::Form::ObjectNotFound }
26
+
27
+ specify do
28
+ expect { user.profile_attributes = { first_name: 'User' } }
29
+ .to change { user.profile.try(:first_name) }
30
+ .to('User')
31
+ end
32
+
33
+ specify do
34
+ expect do
35
+ user.profile_attributes = { identifier: 42, first_name: 'User' }
36
+ end.to raise_error Granite::Form::ObjectNotFound
37
+ end
28
38
 
29
39
  context ':reject_if' do
30
40
  context do
31
41
  before { User.accepts_nested_attributes_for :profile, reject_if: :all_blank }
32
- specify { expect { user.profile_attributes = {first_name: ''} }.not_to change { user.profile } }
42
+
43
+ specify { expect { user.profile_attributes = { first_name: '' } }.not_to(change { user.profile }) }
33
44
  end
34
45
 
35
46
  context do
36
- before { User.accepts_nested_attributes_for :profile, reject_if: ->(attributes) { attributes['first_name'].blank? } }
37
- specify { expect { user.profile_attributes = {first_name: ''} }.not_to change { user.profile } }
47
+ before do
48
+ User.accepts_nested_attributes_for :profile, reject_if: lambda { |attributes|
49
+ attributes['first_name'].blank?
50
+ }
51
+ end
52
+
53
+ specify { expect { user.profile_attributes = { first_name: '' } }.not_to(change { user.profile }) }
38
54
  end
39
55
  end
40
56
 
@@ -42,35 +58,50 @@ shared_examples 'nested attributes' do
42
58
  let(:profile) { Profile.new(first_name: 'User') }
43
59
  let(:user) { User.new profile: profile }
44
60
 
45
- specify { expect { user.profile_attributes = {identifier: 42, first_name: 'User'} }.to raise_error Granite::Form::ObjectNotFound }
46
- specify { expect { user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1'} }.to change { user.profile.first_name }.to('User 1') }
47
- specify { expect { user.profile_attributes = {first_name: 'User 1'} }.to change { user.profile.first_name }.to('User 1') }
48
- specify { expect { user.profile_attributes = {first_name: 'User 1', _destroy: '1'} }.not_to change { user.profile.first_name } }
49
61
  specify do
50
62
  expect do
51
- user.profile_attributes = {first_name: 'User 1', _destroy: '1'}
52
- end.not_to change { user.profile.first_name }
63
+ user.profile_attributes = { identifier: 42, first_name: 'User' }
64
+ end.to raise_error Granite::Form::ObjectNotFound
65
+ end
66
+
67
+ specify do
68
+ expect { user.profile_attributes = { identifier: profile.identifier.to_s, first_name: 'User 1' } }
69
+ .to change { user.profile.first_name }.to('User 1')
70
+ end
71
+
72
+ specify do
73
+ expect { user.profile_attributes = { first_name: 'User 1' } }
74
+ .to change { user.profile.first_name }.to('User 1')
53
75
  end
54
- specify { expect { user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1'} }.to change { user.profile.first_name }.to('User 1') }
76
+
77
+ specify do
78
+ expect { user.profile_attributes = { first_name: 'User 1', _destroy: '1' } }
79
+ .not_to(change { user.profile.first_name })
80
+ end
81
+
55
82
  specify do
56
83
  expect do
57
- user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1'}
84
+ user.profile_attributes = { first_name: 'User 1', _destroy: '1' }
85
+ end.not_to(change { user.profile.first_name })
86
+ end
87
+
88
+ specify do
89
+ expect do
90
+ user.profile_attributes = { identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1' }
58
91
  end.to change { user.profile.first_name }.to('User 1')
59
92
  end
60
93
 
61
94
  context ':allow_destroy' do
62
95
  before { User.accepts_nested_attributes_for :profile, allow_destroy: true }
63
96
 
64
- specify { expect { user.profile_attributes = {first_name: 'User 1', _destroy: '1'} }.not_to change { user.profile.first_name } }
65
97
  specify do
66
- expect do
67
- user.profile_attributes = {first_name: 'User 1', _destroy: '1'}
68
- end.not_to change { user.profile.first_name }
98
+ expect { user.profile_attributes = { first_name: 'User 1', _destroy: '1' } }
99
+ .not_to(change { user.profile.first_name })
69
100
  end
70
- specify { expect { user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1'} }.to change { user.profile }.to(nil) }
101
+
71
102
  specify do
72
103
  expect do
73
- user.profile_attributes = {identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1'}
104
+ user.profile_attributes = { identifier: profile.identifier.to_s, first_name: 'User 1', _destroy: '1' }
74
105
  end.to change { user.profile }.to(nil)
75
106
  end
76
107
  end
@@ -79,7 +110,7 @@ shared_examples 'nested attributes' do
79
110
  before { User.accepts_nested_attributes_for :profile, update_only: true }
80
111
 
81
112
  specify do
82
- expect { user.profile_attributes = {identifier: 42, first_name: 'User 1'} }
113
+ expect { user.profile_attributes = { identifier: 42, first_name: 'User 1' } }
83
114
  .to change { user.profile.first_name }.to('User 1')
84
115
  end
85
116
  end
@@ -94,14 +125,18 @@ shared_examples 'nested attributes' do
94
125
  end
95
126
 
96
127
  specify { expect { user.profile_attributes = {} }.to change { user.profile }.to(an_instance_of(Profile)) }
97
- specify { expect { user.profile_attributes = {first_name: 'User'} }.to change { user.profile.try(:first_name) }.to('User') }
128
+
129
+ specify do
130
+ expect { user.profile_attributes = { first_name: 'User' } }
131
+ .to change { user.profile.try(:first_name) }.to('User')
132
+ end
98
133
 
99
134
  context do
100
135
  let(:profile) { Profile.new(first_name: 'User') }
101
136
  let(:user) { User.new profile: profile }
102
137
 
103
138
  specify do
104
- expect { user.profile_attributes = {identifier: 42, first_name: 'User 1'} }
139
+ expect { user.profile_attributes = { identifier: 42, first_name: 'User 1' } }
105
140
  .to change { user.profile.first_name }.to('User 1')
106
141
  end
107
142
  end
@@ -127,21 +162,25 @@ shared_examples 'nested attributes' do
127
162
  context 'embeds_many' do
128
163
  let(:user) { User.new }
129
164
 
130
- specify { expect { user.projects_attributes = {} }.not_to change { user.projects } }
165
+ specify { expect { user.projects_attributes = {} }.not_to(change { user.projects }) }
166
+
131
167
  specify do
132
- expect { user.projects_attributes = [{title: 'Project 1'}, {title: 'Project 2'}] }
168
+ expect { user.projects_attributes = [{ title: 'Project 1' }, { title: 'Project 2' }] }
133
169
  .to change { user.projects.map(&:title) }.to(['Project 1', 'Project 2'])
134
170
  end
171
+
135
172
  specify do
136
- expect { user.projects_attributes = {1 => {title: 'Project 1'}, 2 => {title: 'Project 2'}} }
173
+ expect { user.projects_attributes = { 1 => { title: 'Project 1' }, 2 => { title: 'Project 2' } } }
137
174
  .to change { user.projects.map(&:title) }.to(['Project 1', 'Project 2'])
138
175
  end
176
+
139
177
  specify do
140
- expect { user.projects_attributes = [{slug: 42, title: 'Project 1'}, {title: 'Project 2'}] }
178
+ expect { user.projects_attributes = [{ slug: 42, title: 'Project 1' }, { title: 'Project 2' }] }
141
179
  .to change { user.projects.map(&:title) }.to(['Project 1', 'Project 2'])
142
180
  end
181
+
143
182
  specify do
144
- expect { user.projects_attributes = [{title: ''}, {title: 'Project 2'}] }
183
+ expect { user.projects_attributes = [{ title: '' }, { title: 'Project 2' }] }
145
184
  .to change { user.projects.map(&:title) }.to(['', 'Project 2'])
146
185
  end
147
186
 
@@ -149,11 +188,12 @@ shared_examples 'nested attributes' do
149
188
  before { User.accepts_nested_attributes_for :projects, limit: 1 }
150
189
 
151
190
  specify do
152
- expect { user.projects_attributes = [{title: 'Project 1'}] }
191
+ expect { user.projects_attributes = [{ title: 'Project 1' }] }
153
192
  .to change { user.projects.map(&:title) }.to(['Project 1'])
154
193
  end
194
+
155
195
  specify do
156
- expect { user.projects_attributes = [{title: 'Project 1'}, {title: 'Project 2'}] }
196
+ expect { user.projects_attributes = [{ title: 'Project 1' }, { title: 'Project 2' }] }
157
197
  .to raise_error Granite::Form::TooManyObjects
158
198
  end
159
199
  end
@@ -161,25 +201,36 @@ shared_examples 'nested attributes' do
161
201
  context ':reject_if' do
162
202
  context do
163
203
  before { User.accepts_nested_attributes_for :projects, reject_if: :all_blank }
204
+
164
205
  specify do
165
- expect { user.projects_attributes = [{title: ''}, {title: 'Project 2'}] }
206
+ expect { user.projects_attributes = [{ title: '' }, { title: 'Project 2' }] }
166
207
  .to change { user.projects.map(&:title) }.to(['Project 2'])
167
208
  end
168
209
  end
169
210
 
170
211
  context do
171
- before { User.accepts_nested_attributes_for :projects, reject_if: ->(attributes) { attributes['title'].blank? } }
212
+ before do
213
+ User.accepts_nested_attributes_for :projects, reject_if: lambda { |attributes|
214
+ attributes['title'].blank?
215
+ }
216
+ end
217
+
172
218
  specify do
173
- expect { user.projects_attributes = [{title: ''}, {title: 'Project 2'}] }
219
+ expect { user.projects_attributes = [{ title: '' }, { title: 'Project 2' }] }
174
220
  .to change { user.projects.map(&:title) }.to(['Project 2'])
175
221
  end
176
222
  end
177
223
 
178
224
  context do
179
- before { User.accepts_nested_attributes_for :projects, reject_if: ->(attributes) { attributes['foobar'].blank? } }
225
+ before do
226
+ User.accepts_nested_attributes_for :projects, reject_if: lambda { |attributes|
227
+ attributes['foobar'].blank?
228
+ }
229
+ end
230
+
180
231
  specify do
181
- expect { user.projects_attributes = [{title: ''}, {title: 'Project 2'}] }
182
- .not_to change { user.projects }
232
+ expect { user.projects_attributes = [{ title: '' }, { title: 'Project 2' }] }
233
+ .not_to(change { user.projects })
183
234
  end
184
235
  end
185
236
  end
@@ -191,53 +242,58 @@ shared_examples 'nested attributes' do
191
242
  specify do
192
243
  expect do
193
244
  user.projects_attributes = [
194
- {slug: projects.first.slug.to_i, title: 'Project 3'},
195
- {title: 'Project 4'}
245
+ { slug: projects.first.slug.to_i, title: 'Project 3' },
246
+ { title: 'Project 4' }
196
247
  ]
197
248
  end
198
249
  .to change { user.projects.map(&:title) }.to(['Project 3', 'Project 2', 'Project 4'])
199
250
  end
251
+
200
252
  specify do
201
253
  expect do
202
254
  user.projects_attributes = [
203
- {slug: projects.first.slug.to_i, title: 'Project 3'},
204
- {slug: 33, title: 'Project 4'}
255
+ { slug: projects.first.slug.to_i, title: 'Project 3' },
256
+ { slug: 33, title: 'Project 4' }
205
257
  ]
206
258
  end
207
259
  .to change { user.projects.map(&:slug) }.to(%w[42 43 33])
208
260
  end
261
+
209
262
  specify do
210
263
  expect do
211
264
  user.projects_attributes = [
212
- {slug: projects.first.slug.to_i, title: 'Project 3'},
213
- {slug: 33, title: 'Project 4', _destroy: 1}
265
+ { slug: projects.first.slug.to_i, title: 'Project 3' },
266
+ { slug: 33, title: 'Project 4', _destroy: 1 }
214
267
  ]
215
268
  end
216
- .not_to change { user.projects.map(&:slug) }
269
+ .not_to(change { user.projects.map(&:slug) })
217
270
  end
271
+
218
272
  specify do
219
273
  expect do
220
274
  user.projects_attributes = {
221
- 1 => {slug: projects.first.slug.to_i, title: 'Project 3'},
222
- 2 => {title: 'Project 4'}
275
+ 1 => { slug: projects.first.slug.to_i, title: 'Project 3' },
276
+ 2 => { title: 'Project 4' }
223
277
  }
224
278
  end
225
279
  .to change { user.projects.map(&:title) }.to(['Project 3', 'Project 2', 'Project 4'])
226
280
  end
281
+
227
282
  specify do
228
283
  expect do
229
284
  user.projects_attributes = [
230
- {slug: projects.first.slug.to_i, title: 'Project 3', _destroy: '1'},
231
- {title: 'Project 4', _destroy: '1'}
285
+ { slug: projects.first.slug.to_i, title: 'Project 3', _destroy: '1' },
286
+ { title: 'Project 4', _destroy: '1' }
232
287
  ]
233
288
  end
234
289
  .to change { user.projects.map(&:title) }.to(['Project 3', 'Project 2'])
235
290
  end
291
+
236
292
  specify do
237
293
  expect do
238
294
  user.projects_attributes = [
239
- {slug: projects.first.slug.to_i, title: 'Project 3', _destroy: '1'},
240
- {title: 'Project 4', _destroy: '1'}
295
+ { slug: projects.first.slug.to_i, title: 'Project 3', _destroy: '1' },
296
+ { title: 'Project 4', _destroy: '1' }
241
297
  ]
242
298
  end
243
299
  .to change { user.projects.map(&:title) }.to(['Project 3', 'Project 2'])
@@ -249,8 +305,8 @@ shared_examples 'nested attributes' do
249
305
  specify do
250
306
  expect do
251
307
  user.projects_attributes = [
252
- {slug: projects.first.slug.to_i, title: 'Project 3', _destroy: '1'},
253
- {title: 'Project 4', _destroy: '1'}
308
+ { slug: projects.first.slug.to_i, title: 'Project 3', _destroy: '1' },
309
+ { title: 'Project 4', _destroy: '1' }
254
310
  ]
255
311
  end
256
312
  .to change { user.projects.map(&:title) }.to(['Project 2'])
@@ -263,8 +319,8 @@ shared_examples 'nested attributes' do
263
319
  specify do
264
320
  expect do
265
321
  user.projects_attributes = [
266
- {slug: projects.first.slug.to_i, title: 'Project 3'},
267
- {title: 'Project 4'}
322
+ { slug: projects.first.slug.to_i, title: 'Project 3' },
323
+ { title: 'Project 4' }
268
324
  ]
269
325
  end
270
326
  .to change { user.projects.map(&:title) }.to(['Project 3', 'Project 2'])
@@ -273,8 +329,8 @@ shared_examples 'nested attributes' do
273
329
  specify do
274
330
  expect do
275
331
  user.projects_attributes = [
276
- {slug: projects.last.slug.to_i, title: 'Project 3'},
277
- {slug: projects.first.slug.to_i.pred, title: 'Project 0'}
332
+ { slug: projects.last.slug.to_i, title: 'Project 3' },
333
+ { slug: projects.first.slug.to_i.pred, title: 'Project 0' }
278
334
  ]
279
335
  end
280
336
  .to change { user.projects.map(&:title) }.to(['Project 1', 'Project 3'])