granite-form 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -2
  3. data/.github/workflows/{ci.yml → ruby.yml} +22 -4
  4. data/.rubocop.yml +1 -1
  5. data/.rubocop_todo.yml +3 -3
  6. data/Appraisals +1 -2
  7. data/CHANGELOG.md +15 -0
  8. data/README.md +6 -15
  9. data/docker-compose.yml +14 -0
  10. data/gemfiles/rails.5.0.gemfile +0 -1
  11. data/gemfiles/rails.5.1.gemfile +0 -1
  12. data/gemfiles/rails.5.2.gemfile +0 -1
  13. data/granite-form.gemspec +15 -15
  14. data/lib/granite/form/active_record/associations.rb +1 -1
  15. data/lib/granite/form/base.rb +1 -2
  16. data/lib/granite/form/errors.rb +0 -15
  17. data/lib/granite/form/model/associations/base.rb +0 -4
  18. data/lib/granite/form/model/associations/collection/embedded.rb +2 -1
  19. data/lib/granite/form/model/associations/collection/proxy.rb +1 -1
  20. data/lib/granite/form/model/associations/embeds_any.rb +7 -0
  21. data/lib/granite/form/model/associations/embeds_many.rb +9 -58
  22. data/lib/granite/form/model/associations/embeds_one.rb +7 -36
  23. data/lib/granite/form/model/associations/nested_attributes.rb +7 -7
  24. data/lib/granite/form/model/associations/persistence_adapters/active_record.rb +0 -4
  25. data/lib/granite/form/model/associations/persistence_adapters/base.rb +0 -4
  26. data/lib/granite/form/model/associations/references_many.rb +0 -32
  27. data/lib/granite/form/model/associations/references_one.rb +0 -28
  28. data/lib/granite/form/model/associations/reflections/embeds_any.rb +1 -1
  29. data/lib/granite/form/model/associations/reflections/embeds_many.rb +1 -1
  30. data/lib/granite/form/model/associations/reflections/embeds_one.rb +11 -1
  31. data/lib/granite/form/model/associations/reflections/references_any.rb +0 -4
  32. data/lib/granite/form/model/associations/reflections/singular.rb +0 -22
  33. data/lib/granite/form/model/associations.rb +0 -6
  34. data/lib/granite/form/model/attributes/attribute.rb +3 -21
  35. data/lib/granite/form/model/attributes/base.rb +5 -23
  36. data/lib/granite/form/model/attributes/reference_many.rb +1 -1
  37. data/lib/granite/form/model/attributes/reference_one.rb +1 -1
  38. data/lib/granite/form/model/attributes/reflections/attribute.rb +2 -8
  39. data/lib/granite/form/model/attributes/reflections/base/build_type_definition.rb +38 -0
  40. data/lib/granite/form/model/attributes/reflections/base.rb +20 -17
  41. data/lib/granite/form/model/attributes/reflections/collection/build_type_definition.rb +19 -0
  42. data/lib/granite/form/model/attributes/reflections/dictionary/build_type_definition.rb +19 -0
  43. data/lib/granite/form/model/attributes/reflections/dictionary.rb +0 -3
  44. data/lib/granite/form/model/attributes/reflections/reference_one.rb +0 -6
  45. data/lib/granite/form/model/attributes/reflections/represents/build_type_definition.rb +73 -0
  46. data/lib/granite/form/model/attributes/reflections/represents.rb +10 -2
  47. data/lib/granite/form/model/attributes/represents.rb +22 -37
  48. data/lib/granite/form/model/attributes.rb +10 -2
  49. data/lib/granite/form/model/persistence.rb +1 -19
  50. data/lib/granite/form/model/representation.rb +1 -0
  51. data/lib/granite/form/model/validations.rb +6 -0
  52. data/lib/granite/form/model.rb +1 -3
  53. data/lib/granite/form/types/active_support/time_zone.rb +2 -0
  54. data/lib/granite/form/types/array.rb +2 -0
  55. data/lib/granite/form/types/big_decimal.rb +2 -0
  56. data/lib/granite/form/types/boolean.rb +2 -0
  57. data/lib/granite/form/types/collection.rb +11 -0
  58. data/lib/granite/form/types/date.rb +2 -0
  59. data/lib/granite/form/types/date_time.rb +2 -0
  60. data/lib/granite/form/types/dictionary.rb +23 -0
  61. data/lib/granite/form/types/float.rb +2 -0
  62. data/lib/granite/form/types/has_subtype.rb +18 -0
  63. data/lib/granite/form/types/hash_with_action_controller_parameters.rb +2 -0
  64. data/lib/granite/form/types/integer.rb +2 -0
  65. data/lib/granite/form/types/object.rb +28 -0
  66. data/lib/granite/form/types/string.rb +2 -0
  67. data/lib/granite/form/types/time.rb +2 -0
  68. data/lib/granite/form/types/uuid.rb +2 -0
  69. data/lib/granite/form/types.rb +3 -0
  70. data/lib/granite/form/util.rb +55 -0
  71. data/lib/granite/form/version.rb +1 -1
  72. data/lib/granite/form.rb +1 -0
  73. data/spec/granite/form/active_record/associations_spec.rb +16 -18
  74. data/spec/granite/form/model/associations/embeds_many_spec.rb +29 -305
  75. data/spec/granite/form/model/associations/embeds_one_spec.rb +27 -212
  76. data/spec/granite/form/model/associations/nested_attributes_spec.rb +0 -95
  77. data/spec/granite/form/model/associations/references_many_spec.rb +5 -326
  78. data/spec/granite/form/model/associations/references_one_spec.rb +7 -279
  79. data/spec/granite/form/model/associations/reflections/embeds_any_spec.rb +1 -2
  80. data/spec/granite/form/model/associations/reflections/embeds_many_spec.rb +18 -26
  81. data/spec/granite/form/model/associations/reflections/embeds_one_spec.rb +16 -23
  82. data/spec/granite/form/model/associations/reflections/references_many_spec.rb +1 -1
  83. data/spec/granite/form/model/associations/reflections/references_one_spec.rb +1 -22
  84. data/spec/granite/form/model/associations/validations_spec.rb +0 -3
  85. data/spec/granite/form/model/associations_spec.rb +3 -24
  86. data/spec/granite/form/model/attributes/attribute_spec.rb +0 -29
  87. data/spec/granite/form/model/attributes/reflections/attribute_spec.rb +0 -9
  88. data/spec/granite/form/model/attributes/reflections/base/build_type_definition_spec.rb +27 -0
  89. data/spec/granite/form/model/attributes/reflections/base_spec.rb +16 -10
  90. data/spec/granite/form/model/attributes/reflections/collection/build_type_definition_spec.rb +24 -0
  91. data/spec/granite/form/model/attributes/reflections/dictionary/build_type_definition_spec.rb +24 -0
  92. data/spec/granite/form/model/attributes/reflections/dictionary_spec.rb +0 -6
  93. data/spec/granite/form/model/attributes/reflections/represents/build_type_definition_spec.rb +129 -0
  94. data/spec/granite/form/model/attributes/reflections/represents_spec.rb +43 -20
  95. data/spec/granite/form/model/attributes/represents_spec.rb +78 -55
  96. data/spec/granite/form/model/attributes_spec.rb +84 -23
  97. data/spec/granite/form/model/dirty_spec.rb +1 -7
  98. data/spec/granite/form/model/persistence_spec.rb +0 -2
  99. data/spec/granite/form/model/representation_spec.rb +4 -7
  100. data/spec/granite/form/model/validations/associated_spec.rb +2 -4
  101. data/spec/granite/form/model/validations/nested_spec.rb +2 -4
  102. data/spec/granite/form/model/validations_spec.rb +28 -1
  103. data/spec/granite/form/types/collection_spec.rb +22 -0
  104. data/spec/granite/form/types/dictionary_spec.rb +32 -0
  105. data/spec/granite/form/types/has_subtype_spec.rb +20 -0
  106. data/spec/granite/form/types/object_spec.rb +50 -4
  107. data/spec/granite/form/util_spec.rb +108 -0
  108. data/spec/spec_helper.rb +0 -15
  109. data/spec/support/active_record.rb +23 -0
  110. data/spec/support/shared/nested_attribute_examples.rb +3 -21
  111. metadata +56 -51
  112. data/.github/workflows/main.yml +0 -29
  113. data/gemfiles/rails.4.2.gemfile +0 -15
  114. data/lib/granite/form/model/attributes/collection.rb +0 -19
  115. data/lib/granite/form/model/attributes/dictionary.rb +0 -28
  116. data/lib/granite/form/model/attributes/localized.rb +0 -44
  117. data/lib/granite/form/model/attributes/reflections/localized.rb +0 -45
  118. data/lib/granite/form/model/callbacks.rb +0 -72
  119. data/lib/granite/form/model/lifecycle.rb +0 -309
  120. data/lib/granite/form/model/localization.rb +0 -26
  121. data/spec/granite/form/model/attributes/collection_spec.rb +0 -72
  122. data/spec/granite/form/model/attributes/dictionary_spec.rb +0 -100
  123. data/spec/granite/form/model/attributes/localized_spec.rb +0 -103
  124. data/spec/granite/form/model/attributes/reflections/localized_spec.rb +0 -37
  125. data/spec/granite/form/model/callbacks_spec.rb +0 -337
  126. data/spec/granite/form/model/lifecycle_spec.rb +0 -356
@@ -1,100 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Granite::Form::Model::Attributes::Dictionary do
4
- before { stub_model(:dummy) }
5
-
6
- def attribute(*args)
7
- options = args.extract_options!
8
- Dummy.add_attribute(Granite::Form::Model::Attributes::Reflections::Dictionary, :field, options)
9
- Dummy.new.attribute(:field)
10
- end
11
-
12
- describe '#read' do
13
- let(:field) do
14
- attribute(type: String,
15
- normalizer: ->(val) { val.delete_if { |_, v| v.nil? } },
16
- default: :world, enum: %w[hello 42])
17
- end
18
-
19
- specify { expect(field.tap { |r| r.write(nil) }.read).to eq({}) }
20
- specify { expect(field.tap { |r| r.write({}) }.read).to eq({}) }
21
- specify { expect(field.tap { |r| r.write(a: nil) }.read).to eq({}) }
22
- specify { expect(field.tap { |r| r.write(a: '') }.read).to eq({}) }
23
- specify { expect(field.tap { |r| r.write(a: 1) }.read).to eq({}) }
24
- specify { expect(field.tap { |r| r.write(a: 42) }.read).to eq('a' => '42') }
25
- specify { expect(field.tap { |r| r.write(a: 'hello', b: '42') }.read).to eq('a' => 'hello', 'b' => '42') }
26
- specify { expect(field.tap { |r| r.write(a: 'hello', b: '1') }.read).to eq('a' => 'hello') }
27
- specify { expect(field.tap { |r| r.write(a: 'hello', x: '42') }.read).to eq('a' => 'hello', 'x' => '42') }
28
-
29
- context do
30
- let(:field) do
31
- attribute(type: String,
32
- normalizer: ->(val) { val.delete_if { |_, v| v.nil? } },
33
- default: :world)
34
- end
35
-
36
- specify { expect(field.tap { |r| r.write(nil) }.read).to eq({}) }
37
- specify { expect(field.tap { |r| r.write({}) }.read).to eq({}) }
38
- specify { expect(field.tap { |r| r.write(a: 1) }.read).to eq('a' => '1') }
39
- specify { expect(field.tap { |r| r.write(a: nil, b: nil) }.read).to eq('a' => 'world', 'b' => 'world') }
40
- specify { expect(field.tap { |r| r.write(a: '') }.read).to eq('a' => '') }
41
- end
42
-
43
- context 'with :keys' do
44
- let(:field) { attribute(type: String, keys: ['a', :b]) }
45
-
46
- specify { expect(field.tap { |r| r.write(nil) }.read).to eq({}) }
47
- specify { expect(field.tap { |r| r.write({}) }.read).to eq({}) }
48
- specify { expect(field.tap { |r| r.write(a: 1, 'b' => 2, c: 3, 'd' => 4) }.read).to eq('a' => '1', 'b' => '2') }
49
- specify { expect(field.tap { |r| r.write(a: 1, c: 3, 'd' => 4) }.read).to eq('a' => '1') }
50
- end
51
- end
52
-
53
- describe '#read_before_type_cast' do
54
- let(:field) { attribute(type: String, default: :world, enum: %w[hello 42]) }
55
-
56
- specify { expect(field.tap { |r| r.write(nil) }.read_before_type_cast).to eq({}) }
57
- specify { expect(field.tap { |r| r.write({}) }.read_before_type_cast).to eq({}) }
58
- specify { expect(field.tap { |r| r.write(a: 1) }.read_before_type_cast).to eq('a' => 1) }
59
- specify { expect(field.tap { |r| r.write(a: nil) }.read_before_type_cast).to eq('a' => :world) }
60
- specify { expect(field.tap { |r| r.write(a: '') }.read_before_type_cast).to eq('a' => '') }
61
- specify { expect(field.tap { |r| r.write(a: 42) }.read_before_type_cast).to eq('a' => 42) }
62
- specify { expect(field.tap { |r| r.write(a: 'hello', b: '42') }.read_before_type_cast).to eq('a' => 'hello', 'b' => '42') }
63
- specify { expect(field.tap { |r| r.write(a: 'hello', b: '1') }.read_before_type_cast).to eq('a' => 'hello', 'b' => '1') }
64
- specify { expect(field.tap { |r| r.write(a: 'hello', x: '42') }.read_before_type_cast).to eq('a' => 'hello', 'x' => '42') }
65
-
66
- context do
67
- let(:field) { attribute(type: String, default: :world) }
68
-
69
- specify { expect(field.tap { |r| r.write(nil) }.read_before_type_cast).to eq({}) }
70
- specify { expect(field.tap { |r| r.write({}) }.read_before_type_cast).to eq({}) }
71
- specify { expect(field.tap { |r| r.write(a: 1) }.read_before_type_cast).to eq('a' => 1) }
72
- specify { expect(field.tap { |r| r.write(a: nil, b: nil) }.read_before_type_cast).to eq('a' => :world, 'b' => :world) }
73
- specify { expect(field.tap { |r| r.write(a: '') }.read_before_type_cast).to eq('a' => '') }
74
- end
75
-
76
- context 'with :keys' do
77
- let(:field) { attribute(type: String, keys: ['a', :b]) }
78
-
79
- specify { expect(field.tap { |r| r.write(nil) }.read_before_type_cast).to eq({}) }
80
- specify { expect(field.tap { |r| r.write({}) }.read_before_type_cast).to eq({}) }
81
- specify do
82
- expect(field.tap { |r| r.write(a: 1, 'b' => 2, c: 3, 'd' => 4) }.read_before_type_cast)
83
- .to eq('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4)
84
- end
85
- end
86
- end
87
-
88
- context 'integration' do
89
- before do
90
- stub_model(:post) do
91
- dictionary :options, type: String
92
- end
93
- end
94
-
95
- specify { expect(Post.new(options: {a: 'hello', b: 42}).options).to eq('a' => 'hello', 'b' => '42') }
96
- specify { expect(Post.new(options: {a: 'hello', b: 42}).options_before_type_cast).to eq('a' => 'hello', 'b' => 42) }
97
- specify { expect(Post.new.options?).to eq(false) }
98
- specify { expect(Post.new(options: {a: 'hello', b: 42}).options?).to eq(true) }
99
- end
100
- end
@@ -1,103 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Granite::Form::Model::Attributes::Localized do
4
- before { stub_model(:dummy) }
5
-
6
- def attribute(*args)
7
- options = args.extract_options!
8
- Dummy.add_attribute(Granite::Form::Model::Attributes::Reflections::Localized, :field, options)
9
- Dummy.new.attribute(:field)
10
- end
11
-
12
- describe '#read' do
13
- let(:field) { attribute(type: String, default: :world, enum: %w[hello 42]) }
14
-
15
- specify { expect(field.tap { |r| r.write(nil) }.read).to eq({}) }
16
- specify { expect(field.tap { |r| r.write(en: 'hello') }.read).to eq('en' => 'hello') }
17
- specify { expect(field.tap { |r| r.write(en: 42) }.read).to eq('en' => '42') }
18
- specify { expect(field.tap { |r| r.write(en: 43) }.read).to eq('en' => nil) }
19
- specify { expect(field.tap { |r| r.write(en: '') }.read).to eq('en' => nil) }
20
- specify { expect(field.tap { |r| r.write(en: nil) }.read).to eq('en' => nil) }
21
- specify { expect(field.tap { |r| r.write(en: 'hello', ru: 42) }.read).to eq('en' => 'hello', 'ru' => '42') }
22
-
23
- context do
24
- let(:field) { attribute(type: String, default: :world) }
25
-
26
- specify { expect(field.tap { |r| r.write(nil) }.read).to eq({}) }
27
- specify { expect(field.tap { |r| r.write(en: 'hello') }.read).to eq('en' => 'hello') }
28
- specify { expect(field.tap { |r| r.write(en: 42) }.read).to eq('en' => '42') }
29
- specify { expect(field.tap { |r| r.write(en: '') }.read).to eq('en' => '') }
30
- specify { expect(field.tap { |r| r.write(en: nil) }.read).to eq('en' => 'world') }
31
- end
32
- end
33
-
34
- describe '#read_before_type_cast' do
35
- let(:field) { attribute(type: String, default: :world, enum: %w[hello 42]) }
36
-
37
- specify { expect(field.tap { |r| r.write(nil) }.read_before_type_cast).to eq({}) }
38
- specify { expect(field.tap { |r| r.write(en: 'hello') }.read_before_type_cast).to eq('en' => 'hello') }
39
- specify { expect(field.tap { |r| r.write(en: 42) }.read_before_type_cast).to eq('en' => 42) }
40
- specify { expect(field.tap { |r| r.write(en: 43) }.read_before_type_cast).to eq('en' => 43) }
41
- specify { expect(field.tap { |r| r.write(en: '') }.read_before_type_cast).to eq('en' => '') }
42
- specify { expect(field.tap { |r| r.write(en: nil) }.read_before_type_cast).to eq('en' => :world) }
43
- specify { expect(field.tap { |r| r.write(en: 'hello', ru: 42) }.read_before_type_cast).to eq('en' => 'hello', 'ru' => 42) }
44
-
45
- context do
46
- let(:field) { attribute(type: String, default: :world) }
47
-
48
- specify { expect(field.tap { |r| r.write(nil) }.read_before_type_cast).to eq({}) }
49
- specify { expect(field.tap { |r| r.write(en: 'hello') }.read_before_type_cast).to eq('en' => 'hello') }
50
- specify { expect(field.tap { |r| r.write(en: 42) }.read_before_type_cast).to eq('en' => 42) }
51
- specify { expect(field.tap { |r| r.write(en: '') }.read_before_type_cast).to eq('en' => '') }
52
- specify { expect(field.tap { |r| r.write(en: nil) }.read_before_type_cast).to eq('en' => :world) }
53
- end
54
- end
55
-
56
- context 'integration' do
57
- let(:klass) do
58
- Class.new do
59
- include Granite::Form::Model
60
- include Granite::Form::Model::Localization
61
-
62
- localized :name, type: String
63
- end
64
- end
65
- let(:translations) { {en: 'Hello', ru: 'Привет'} }
66
- before { I18n.locale = :en }
67
-
68
- describe '#name_translations' do
69
- subject { klass.new name_translations: translations }
70
- its(:name_translations) { should == translations.stringify_keys }
71
- its(:name) { should == translations[:en] }
72
- end
73
-
74
- describe '#name' do
75
- subject { klass.new name: 'Hello' }
76
- its(:name_translations) { should == {'en' => 'Hello'} }
77
- its(:name) { should == 'Hello' }
78
- end
79
-
80
- describe '#name_before_type_cast' do
81
- let(:object) { Object.new }
82
- subject { klass.new name: object }
83
- its(:name_before_type_cast) { should == object }
84
- end
85
-
86
- context 'fallbacks' do
87
- subject { klass.new name_translations: {ru: 'Привет'} }
88
- context do
89
- its(:name) { should be_nil }
90
- end
91
-
92
- context do
93
- before do
94
- require 'i18n/backend/fallbacks'
95
- I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
96
- I18n.fallbacks[:en] = [:ru]
97
- end
98
- after { I18n.fallbacks = false }
99
- its(:name) { should == 'Привет' }
100
- end
101
- end
102
- end
103
- end
@@ -1,37 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Granite::Form::Model::Attributes::Reflections::Localized do
4
- def reflection(options = {})
5
- described_class.new(:field, options)
6
- end
7
-
8
- describe '.build' do
9
- before { stub_class(:target) }
10
-
11
- specify do
12
- described_class.build(Class.new, Target, :field)
13
-
14
- expect(Target).to be_method_defined(:field_translations)
15
- expect(Target).to be_method_defined(:field_translations=)
16
- expect(Target).to be_method_defined(:field)
17
- expect(Target).to be_method_defined(:field=)
18
- expect(Target).to be_method_defined(:field?)
19
- expect(Target).to be_method_defined(:field_before_type_cast)
20
- end
21
- end
22
-
23
- describe '#generate_methods' do
24
- before { stub_class(:target) }
25
-
26
- specify do
27
- described_class.generate_methods(:field_alias, Target)
28
-
29
- expect(Target).to be_method_defined(:field_alias_translations)
30
- expect(Target).to be_method_defined(:field_alias_translations=)
31
- expect(Target).to be_method_defined(:field_alias)
32
- expect(Target).to be_method_defined(:field_alias=)
33
- expect(Target).to be_method_defined(:field_alias?)
34
- expect(Target).to be_method_defined(:field_alias_before_type_cast)
35
- end
36
- end
37
- end
@@ -1,337 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Granite::Form::Model::Callbacks do
4
- before do
5
- stub_model(:user) do
6
- include Granite::Form::Model::Callbacks
7
- attribute :actions, Array, default: []
8
-
9
- def append(action)
10
- self.actions = actions + [action]
11
- end
12
-
13
- define_create { append :create }
14
- define_update { append :update }
15
- define_destroy { append :destroy }
16
- end
17
- end
18
-
19
- describe '.after_initialize' do
20
- before do
21
- User.after_initialize { append :after_initialize }
22
- end
23
-
24
- specify { expect(User.new.actions).to eq([:after_initialize]) }
25
- specify { expect(User.create.actions).to eq(%i[after_initialize create]) }
26
- end
27
-
28
- describe '.before_save, .after_save' do
29
- before do
30
- User.before_save { append :before_save }
31
- User.after_save { append :after_save }
32
- end
33
-
34
- specify { expect(User.create.actions).to eq(%i[before_save create after_save]) }
35
- specify { expect(User.new.tap(&:save).actions).to eq(%i[before_save create after_save]) }
36
- specify { expect(User.new.tap { |u| u.update({}) }.actions).to eq(%i[before_save create after_save]) }
37
- specify { expect(User.create.tap(&:save).actions).to eq(%i[before_save create after_save before_save update after_save]) }
38
- specify { expect(User.create.tap { |u| u.update({}) }.actions).to eq(%i[before_save create after_save before_save update after_save]) }
39
-
40
- specify { expect(User.new.tap { |u| u.save { false } }.actions).to eq([:before_save]) }
41
- specify { expect(User.create.tap { |u| u.save { false } }.actions).to eq(%i[before_save create after_save before_save]) }
42
- end
43
-
44
- describe '.around_save' do
45
- before do
46
- User.around_save do |_, block|
47
- append :before_around_save
48
- block.call
49
- append :after_around_save
50
- end
51
- end
52
-
53
- specify { expect(User.create.actions).to eq(%i[before_around_save create after_around_save]) }
54
- specify { expect(User.new.tap(&:save).actions).to eq(%i[before_around_save create after_around_save]) }
55
- specify { expect(User.new.tap { |u| u.update({}) }.actions).to eq(%i[before_around_save create after_around_save]) }
56
- specify { expect(User.create.tap(&:save).actions).to eq(%i[before_around_save create after_around_save before_around_save update after_around_save]) }
57
- specify { expect(User.create.tap { |u| u.update({}) }.actions).to eq(%i[before_around_save create after_around_save before_around_save update after_around_save]) }
58
-
59
- specify { expect(User.new.tap { |u| u.save { false } }.actions).to eq(%i[before_around_save after_around_save]) }
60
- specify { expect(User.create.tap { |u| u.save { false } }.actions).to eq(%i[before_around_save create after_around_save before_around_save after_around_save]) }
61
- end
62
-
63
- describe '.before_create, .after_create' do
64
- before do
65
- User.before_create { append :before_create }
66
- User.after_create { append :after_create }
67
- end
68
-
69
- specify { expect(User.create.actions).to eq(%i[before_create create after_create]) }
70
- specify { expect(User.new.tap(&:save).actions).to eq(%i[before_create create after_create]) }
71
- specify { expect(User.new.tap { |u| u.update({}) }.actions).to eq(%i[before_create create after_create]) }
72
- specify { expect(User.create.tap(&:save).actions).to eq(%i[before_create create after_create update]) }
73
- specify { expect(User.create.tap { |u| u.update({}) }.actions).to eq(%i[before_create create after_create update]) }
74
-
75
- specify { expect(User.new.tap { |u| u.save { false } }.actions).to eq([:before_create]) }
76
- end
77
-
78
- describe '.around_create' do
79
- before do
80
- User.around_create do |_, block|
81
- append :before_around_create
82
- block.call
83
- append :after_around_create
84
- end
85
- end
86
-
87
- specify { expect(User.create.actions).to eq(%i[before_around_create create after_around_create]) }
88
- specify { expect(User.new.tap(&:save).actions).to eq(%i[before_around_create create after_around_create]) }
89
- specify { expect(User.new.tap { |u| u.update({}) }.actions).to eq(%i[before_around_create create after_around_create]) }
90
- specify { expect(User.create.tap(&:save).actions).to eq(%i[before_around_create create after_around_create update]) }
91
- specify { expect(User.create.tap { |u| u.update({}) }.actions).to eq(%i[before_around_create create after_around_create update]) }
92
-
93
- specify { expect(User.new.tap { |u| u.save { false } }.actions).to eq(%i[before_around_create after_around_create]) }
94
- end
95
-
96
- describe '.before_update, .after_update' do
97
- before do
98
- User.before_update { append :before_update }
99
- User.after_update { append :after_update }
100
- end
101
-
102
- specify { expect(User.create.actions).to eq([:create]) }
103
- specify { expect(User.new.tap(&:save).actions).to eq([:create]) }
104
- specify { expect(User.new.tap { |u| u.update({}) }.actions).to eq([:create]) }
105
- specify { expect(User.create.tap(&:save).actions).to eq(%i[create before_update update after_update]) }
106
- specify { expect(User.create.tap { |u| u.update({}) }.actions).to eq(%i[create before_update update after_update]) }
107
-
108
- specify { expect(User.create.tap { |u| u.save { false } }.actions).to eq(%i[create before_update]) }
109
- end
110
-
111
- describe '.around_update' do
112
- before do
113
- User.around_update do |_, block|
114
- append :before_around_update
115
- block.call
116
- append :after_around_update
117
- end
118
- end
119
-
120
- specify { expect(User.create.actions).to eq([:create]) }
121
- specify { expect(User.new.tap(&:save).actions).to eq([:create]) }
122
- specify { expect(User.new.tap { |u| u.update({}) }.actions).to eq([:create]) }
123
- specify { expect(User.create.tap(&:save).actions).to eq(%i[create before_around_update update after_around_update]) }
124
- specify { expect(User.create.tap { |u| u.update({}) }.actions).to eq(%i[create before_around_update update after_around_update]) }
125
-
126
- specify { expect(User.create.tap { |u| u.save { false } }.actions).to eq(%i[create before_around_update after_around_update]) }
127
- end
128
-
129
- describe '.before_validation, .after_validation,
130
- .before_save, .after_save, .around_save,
131
- .before_create, .after_create, .around_create,
132
- .before_update, .after_update, .around_update
133
- .before_destroy, .after_destroy, .around_destroy' do
134
- before do
135
- User.before_validation { append :before_validation }
136
- User.after_validation { append :after_validation }
137
-
138
- User.before_save { append :before_save }
139
- User.after_save { append :after_save }
140
- User.around_save do |_, block|
141
- append :before_around_save
142
- block.call
143
- append :after_around_save
144
- end
145
-
146
- User.before_create { append :before_create }
147
- User.after_create { append :after_create }
148
- User.around_create do |_, block|
149
- append :before_around_create
150
- block.call
151
- append :after_around_create
152
- end
153
-
154
- User.before_update { append :before_update }
155
- User.after_update { append :after_update }
156
- User.around_update do |_, block|
157
- append :before_around_update
158
- block.call
159
- append :after_around_update
160
- end
161
-
162
- User.before_destroy { append :before_destroy }
163
- User.after_destroy { append :after_destroy }
164
- User.around_destroy do |_, block|
165
- append :before_around_destroy
166
- block.call
167
- append :after_around_destroy
168
- end
169
- end
170
-
171
- specify do
172
- expect(User.create.tap(&:save).destroy.actions).to eq(%i[
173
- before_validation after_validation
174
- before_save before_around_save
175
- before_create before_around_create
176
- create
177
- after_around_create after_create
178
- after_around_save after_save
179
- before_validation after_validation
180
- before_save before_around_save
181
- before_update before_around_update
182
- update
183
- after_around_update after_update
184
- after_around_save after_save
185
- before_destroy before_around_destroy
186
- destroy
187
- after_around_destroy after_destroy
188
- ])
189
- end
190
- end
191
-
192
- describe '.before_destroy, .after_destroy' do
193
- before do
194
- User.before_destroy { append :before_destroy }
195
- User.after_destroy { append :after_destroy }
196
- end
197
-
198
- specify { expect(User.new.destroy.actions).to eq(%i[before_destroy destroy after_destroy]) }
199
- specify { expect(User.create.destroy.actions).to eq(%i[create before_destroy destroy after_destroy]) }
200
-
201
- specify { expect(User.new.destroy { false }.actions).to eq([:before_destroy]) }
202
- specify { expect(User.create.destroy { false }.actions).to eq(%i[create before_destroy]) }
203
- end
204
-
205
- describe '.around_destroy' do
206
- before do
207
- User.around_destroy do |_, block|
208
- append :before_around_destroy
209
- block.call
210
- append :after_around_destroy
211
- end
212
- end
213
-
214
- specify { expect(User.new.destroy.actions).to eq(%i[before_around_destroy destroy after_around_destroy]) }
215
- specify { expect(User.create.destroy.actions).to eq(%i[create before_around_destroy destroy after_around_destroy]) }
216
-
217
- specify { expect(User.new.destroy { false }.actions).to eq(%i[before_around_destroy after_around_destroy]) }
218
- specify { expect(User.create.destroy { false }.actions).to eq(%i[create before_around_destroy after_around_destroy]) }
219
- end
220
-
221
- context 'unsavable, undestroyable' do
222
- before do
223
- stub_model(:user) do
224
- include Granite::Form::Model::Callbacks
225
-
226
- attribute :actions, Array, default: []
227
- attribute :validated, Boolean, default: false
228
-
229
- validates :validated, presence: true
230
-
231
- def append(action)
232
- self.actions = actions + [action]
233
- end
234
- end
235
- end
236
-
237
- before do
238
- User.before_validation { append :before_validation }
239
- User.after_validation { append :after_validation }
240
-
241
- User.before_save { append :before_save }
242
- User.after_save { append :after_save }
243
- User.around_save do |&block|
244
- append :before_around_save
245
- block.call
246
- append :after_around_save
247
- end
248
-
249
- User.before_create { append :before_create }
250
- User.after_create { append :after_create }
251
- User.around_create do |&block|
252
- append :before_around_create
253
- block.call
254
- append :after_around_create
255
- end
256
-
257
- User.before_update { append :before_update }
258
- User.after_update { append :after_update }
259
- User.around_update do |&block|
260
- append :before_around_update
261
- block.call
262
- append :after_around_update
263
- end
264
-
265
- User.before_destroy { append :before_destroy }
266
- User.after_destroy { append :after_destroy }
267
- User.around_destroy do |&block|
268
- append :before_around_destroy
269
- block.call
270
- append :after_around_destroy
271
- end
272
- end
273
-
274
- let(:user) { User.new }
275
-
276
- specify do
277
- begin
278
- user.save
279
- rescue Granite::Form::UnsavableObject
280
- expect(user.actions).to eq([])
281
- end
282
- end
283
-
284
- specify do
285
- begin
286
- user.save!
287
- rescue Granite::Form::UnsavableObject
288
- expect(user.actions).to eq([])
289
- end
290
- end
291
-
292
- specify do
293
- user.save { true }
294
- expect(user.actions).to eq(%i[before_validation after_validation])
295
- end
296
-
297
- specify do
298
- begin
299
- user.save! { true }
300
- rescue Granite::Form::ValidationError
301
- expect(user.actions).to eq(%i[before_validation after_validation])
302
- end
303
- end
304
-
305
- specify do
306
- begin
307
- user.update({})
308
- rescue Granite::Form::UnsavableObject
309
- expect(user.actions).to eq([])
310
- end
311
- end
312
-
313
- specify do
314
- begin
315
- user.update!({})
316
- rescue Granite::Form::UnsavableObject
317
- expect(user.actions).to eq([])
318
- end
319
- end
320
-
321
- specify do
322
- begin
323
- user.destroy
324
- rescue Granite::Form::UndestroyableObject
325
- expect(user.actions).to eq([])
326
- end
327
- end
328
-
329
- specify do
330
- begin
331
- user.destroy!
332
- rescue Granite::Form::UndestroyableObject
333
- expect(user.actions).to eq([])
334
- end
335
- end
336
- end
337
- end