granite-form 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) 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 +7 -0
  8. data/README.md +0 -2
  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 +5 -5
  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/references_any.rb +0 -4
  30. data/lib/granite/form/model/associations/reflections/references_one.rb +0 -2
  31. data/lib/granite/form/model/associations/reflections/singular.rb +0 -8
  32. data/lib/granite/form/model/associations.rb +0 -6
  33. data/lib/granite/form/model/attributes/base.rb +1 -1
  34. data/lib/granite/form/model/attributes/reflections/attribute.rb +0 -6
  35. data/lib/granite/form/model/attributes/reflections/base.rb +8 -7
  36. data/lib/granite/form/model/attributes/reflections/reference_one.rb +0 -6
  37. data/lib/granite/form/model/persistence.rb +1 -19
  38. data/lib/granite/form/model.rb +0 -2
  39. data/lib/granite/form/version.rb +1 -1
  40. data/spec/granite/form/active_record/associations_spec.rb +16 -18
  41. data/spec/granite/form/model/associations/embeds_many_spec.rb +29 -305
  42. data/spec/granite/form/model/associations/embeds_one_spec.rb +27 -212
  43. data/spec/granite/form/model/associations/nested_attributes_spec.rb +0 -95
  44. data/spec/granite/form/model/associations/references_many_spec.rb +5 -326
  45. data/spec/granite/form/model/associations/references_one_spec.rb +6 -278
  46. data/spec/granite/form/model/associations/reflections/embeds_any_spec.rb +1 -2
  47. data/spec/granite/form/model/associations/reflections/embeds_many_spec.rb +18 -26
  48. data/spec/granite/form/model/associations/reflections/embeds_one_spec.rb +16 -23
  49. data/spec/granite/form/model/associations/reflections/references_many_spec.rb +1 -1
  50. data/spec/granite/form/model/associations/reflections/references_one_spec.rb +1 -22
  51. data/spec/granite/form/model/associations/validations_spec.rb +0 -3
  52. data/spec/granite/form/model/associations_spec.rb +3 -24
  53. data/spec/granite/form/model/dirty_spec.rb +1 -1
  54. data/spec/granite/form/model/persistence_spec.rb +0 -2
  55. data/spec/granite/form/model/validations/associated_spec.rb +2 -4
  56. data/spec/granite/form/model/validations/nested_spec.rb +2 -4
  57. data/spec/spec_helper.rb +0 -15
  58. data/spec/support/active_record.rb +20 -0
  59. data/spec/support/shared/nested_attribute_examples.rb +3 -21
  60. metadata +32 -38
  61. data/.github/workflows/main.yml +0 -29
  62. data/gemfiles/rails.4.2.gemfile +0 -15
  63. data/lib/granite/form/model/callbacks.rb +0 -72
  64. data/lib/granite/form/model/lifecycle.rb +0 -309
  65. data/spec/granite/form/model/callbacks_spec.rb +0 -337
  66. data/spec/granite/form/model/lifecycle_spec.rb +0 -356
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: granite-form
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
- - pyromaniac
7
+ - Toptal Engineering
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-12 00:00:00.000000000 Z
11
+ date: 2022-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.0'
19
+ version: '5.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '4.0'
26
+ version: '5.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activerecord
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '4.0'
33
+ version: '5.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '4.0'
40
+ version: '5.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: appraisal
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pg
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rake
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -136,20 +150,6 @@ dependencies:
136
150
  - - '='
137
151
  - !ruby/object:Gem::Version
138
152
  version: 0.52.1
139
- - !ruby/object:Gem::Dependency
140
- name: sqlite3
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: uuidtools
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -170,28 +170,28 @@ dependencies:
170
170
  requirements:
171
171
  - - ">="
172
172
  - !ruby/object:Gem::Version
173
- version: '4.0'
173
+ version: '5.0'
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
- version: '4.0'
180
+ version: '5.0'
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: activesupport
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
185
  - - ">="
186
186
  - !ruby/object:Gem::Version
187
- version: '4.0'
187
+ version: '5.0'
188
188
  type: :runtime
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
- version: '4.0'
194
+ version: '5.0'
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: tzinfo
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -207,16 +207,14 @@ dependencies:
207
207
  - !ruby/object:Gem::Version
208
208
  version: '0'
209
209
  description: Making object from any hash or hash array
210
- email:
211
- - kinwizard@gmail.com
210
+ email:
212
211
  executables: []
213
212
  extensions: []
214
213
  extra_rdoc_files: []
215
214
  files:
216
215
  - ".codeclimate.yml"
217
216
  - ".github/CODEOWNERS"
218
- - ".github/workflows/ci.yml"
219
- - ".github/workflows/main.yml"
217
+ - ".github/workflows/ruby.yml"
220
218
  - ".gitignore"
221
219
  - ".rspec"
222
220
  - ".rubocop.yml"
@@ -228,7 +226,7 @@ files:
228
226
  - LICENSE
229
227
  - README.md
230
228
  - Rakefile
231
- - gemfiles/rails.4.2.gemfile
229
+ - docker-compose.yml
232
230
  - gemfiles/rails.5.0.gemfile
233
231
  - gemfiles/rails.5.1.gemfile
234
232
  - gemfiles/rails.5.2.gemfile
@@ -284,10 +282,8 @@ files:
284
282
  - lib/granite/form/model/attributes/reflections/reference_one.rb
285
283
  - lib/granite/form/model/attributes/reflections/represents.rb
286
284
  - lib/granite/form/model/attributes/represents.rb
287
- - lib/granite/form/model/callbacks.rb
288
285
  - lib/granite/form/model/conventions.rb
289
286
  - lib/granite/form/model/dirty.rb
290
- - lib/granite/form/model/lifecycle.rb
291
287
  - lib/granite/form/model/localization.rb
292
288
  - lib/granite/form/model/persistence.rb
293
289
  - lib/granite/form/model/primary.rb
@@ -343,10 +339,8 @@ files:
343
339
  - spec/granite/form/model/attributes/reflections/represents_spec.rb
344
340
  - spec/granite/form/model/attributes/represents_spec.rb
345
341
  - spec/granite/form/model/attributes_spec.rb
346
- - spec/granite/form/model/callbacks_spec.rb
347
342
  - spec/granite/form/model/conventions_spec.rb
348
343
  - spec/granite/form/model/dirty_spec.rb
349
- - spec/granite/form/model/lifecycle_spec.rb
350
344
  - spec/granite/form/model/persistence_spec.rb
351
345
  - spec/granite/form/model/primary_spec.rb
352
346
  - spec/granite/form/model/representation_spec.rb
@@ -370,12 +364,13 @@ files:
370
364
  - spec/granite/form/types/uuid_spec.rb
371
365
  - spec/granite/form_spec.rb
372
366
  - spec/spec_helper.rb
367
+ - spec/support/active_record.rb
373
368
  - spec/support/model_helpers.rb
374
369
  - spec/support/muffle_helper.rb
375
370
  - spec/support/shared/nested_attribute_examples.rb
376
371
  - spec/support/shared/type_examples.rb
377
372
  - spec/support/translations.rb
378
- homepage: ''
373
+ homepage: https://github.com/toptal/granite-form
379
374
  licenses: []
380
375
  metadata: {}
381
376
  post_install_message:
@@ -386,7 +381,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
386
381
  requirements:
387
382
  - - ">="
388
383
  - !ruby/object:Gem::Version
389
- version: '0'
384
+ version: 2.4.0
390
385
  required_rubygems_version: !ruby/object:Gem::Requirement
391
386
  requirements:
392
387
  - - ">="
@@ -428,10 +423,8 @@ test_files:
428
423
  - spec/granite/form/model/attributes/reflections/represents_spec.rb
429
424
  - spec/granite/form/model/attributes/represents_spec.rb
430
425
  - spec/granite/form/model/attributes_spec.rb
431
- - spec/granite/form/model/callbacks_spec.rb
432
426
  - spec/granite/form/model/conventions_spec.rb
433
427
  - spec/granite/form/model/dirty_spec.rb
434
- - spec/granite/form/model/lifecycle_spec.rb
435
428
  - spec/granite/form/model/persistence_spec.rb
436
429
  - spec/granite/form/model/primary_spec.rb
437
430
  - spec/granite/form/model/representation_spec.rb
@@ -455,6 +448,7 @@ test_files:
455
448
  - spec/granite/form/types/uuid_spec.rb
456
449
  - spec/granite/form_spec.rb
457
450
  - spec/spec_helper.rb
451
+ - spec/support/active_record.rb
458
452
  - spec/support/model_helpers.rb
459
453
  - spec/support/muffle_helper.rb
460
454
  - spec/support/shared/nested_attribute_examples.rb
@@ -1,29 +0,0 @@
1
- name: Ruby
2
-
3
- on: [push]
4
-
5
- jobs:
6
- spec:
7
- runs-on: ubuntu-latest
8
- name: Run specs in ruby v${{ matrix.ruby }} rails v${{ matrix.rails }}
9
- strategy:
10
- matrix:
11
- ruby: [ '2.6', '2.7', '3.0' ]
12
- rails: [ '6.0', '6.1' ]
13
- steps:
14
- - uses: actions/checkout@v2
15
-
16
- - name: Set up Ruby
17
- uses: ruby/setup-ruby@v1
18
- with:
19
- ruby-version: ${{ matrix.ruby }}
20
-
21
- - name: Install dependencies
22
- env:
23
- BUNDLE_GEMFILE: gemfiles/rails.${{ matrix.rails }}.gemfile
24
- run: bundle install
25
-
26
- - name: Run specs
27
- env:
28
- BUNDLE_GEMFILE: gemfiles/rails.${{ matrix.rails }}.gemfile
29
- run: bundle exec rake spec
@@ -1,15 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activesupport", "~> 4.2.0"
6
- gem "activemodel", "~> 4.2.0"
7
- gem "activerecord", "~> 4.2.0"
8
- gem "sqlite3", "~> 1.3.6"
9
-
10
- group :test do
11
- gem "guard"
12
- gem "guard-rspec"
13
- end
14
-
15
- gemspec path: "../"
@@ -1,72 +0,0 @@
1
- module Granite
2
- module Form
3
- module Model
4
- # == Callbacks for Granite::Form::Model lifecycle
5
- #
6
- # Provides ActiveModel callbacks support for lifecycle
7
- # actions.
8
- #
9
- # class Book
10
- # include Granite::Form::Model
11
- #
12
- # attribute :id, Integer
13
- # attribute :title, String
14
- #
15
- # define_save do
16
- # REDIS.set(id, attributes.to_json)
17
- # end
18
- #
19
- # define_destroy do
20
- # REDIS.del(instance.id)
21
- # end
22
- #
23
- # after_initialize :setup_id
24
- # before_save :do_something
25
- # around_update do |&block|
26
- # ...
27
- # block.call
28
- # ...
29
- # end
30
- # after_destroy { ... }
31
- # end
32
- #
33
- module Callbacks
34
- extend ActiveSupport::Concern
35
-
36
- included do
37
- extend ActiveModel::Callbacks
38
-
39
- include ActiveModel::Validations::Callbacks
40
- include Lifecycle
41
- prepend PrependMethods
42
-
43
- define_model_callbacks :initialize, only: :after
44
- define_model_callbacks :save, :create, :update, :destroy
45
- end
46
-
47
- module PrependMethods
48
- def initialize(*_)
49
- super
50
- run_callbacks :initialize
51
- end
52
-
53
- def save_object(&block)
54
- run_callbacks(:save) { super(&block) }
55
- end
56
-
57
- def create_object(&block)
58
- run_callbacks(:create) { super(&block) }
59
- end
60
-
61
- def update_object(&block)
62
- run_callbacks(:update) { super(&block) }
63
- end
64
-
65
- def destroy_object(&block)
66
- run_callbacks(:destroy) { super(&block) }
67
- end
68
- end
69
- end
70
- end
71
- end
72
- end
@@ -1,309 +0,0 @@
1
- module Granite
2
- module Form
3
- module Model
4
- # == Lifecycle methods for Granite::Form::Model
5
- #
6
- # Provides methods +save+ and +destroy+ and its bang variants.
7
- # Also, patches +create+ and +update_attributes+ methods by adding
8
- # save at the end.
9
- #
10
- # You can define save or destroy performers with <tt>define_<action></tt>
11
- # methods. Create and update performers might be defined instead of
12
- # save performer:
13
- #
14
- # class Book
15
- # include Granite::Form::Model
16
- # include Granite::Form::Model::Lifecycle
17
- #
18
- # attribute :id, Integer
19
- # attribute :title, String
20
- #
21
- # define_save do # executes in the instance scope
22
- # REDIS.set(id, attributes.to_json)
23
- # end
24
- #
25
- # define_destroy do
26
- # REDIS.del(id)
27
- # end
28
- # end
29
- #
30
- # class Author
31
- # include Granite::Form::Model
32
- # include Granite::Form::Model::Lifecycle
33
- #
34
- # attribute :id, Integer
35
- # attribute :name, String
36
- #
37
- # define_create do # will be called on create only
38
- # REDIS.sadd('author_ids', id)
39
- # REDIS.set(id, attributes.to_json)
40
- # end
41
- #
42
- # define_update do # will be called on update only
43
- # REDIS.set(id, attributes.to_json)
44
- # end
45
- # end
46
- #
47
- # In case of undefined performer Granite::Form::UnsavableObject
48
- # or Granite::Form::UndestroyableObject will be raised respectively.
49
- #
50
- # If performers was not defined in model, they cat be passed as
51
- # blocks to `save`, `update` and `destroy` methods:
52
- #
53
- # authos.save { REDIS.set(id, attributes.to_json) }
54
- # authos.update { REDIS.set(id, attributes.to_json) }
55
- # authos.destroy { REDIS.del(id) }
56
- #
57
- # Save and destroy processes acts almost the save way as
58
- # ActiveRecord's (with +persisted?+ and +destroyed?+ methods
59
- # affecting).
60
- #
61
- module Lifecycle
62
- extend ActiveSupport::Concern
63
-
64
- included do
65
- include Persistence
66
-
67
- class_attribute(*%i[save create update destroy].map { |action| "_#{action}_performer" })
68
- private(*%i[save create update destroy].map { |action| "_#{action}_performer=" })
69
- end
70
-
71
- module ClassMethods
72
- # <tt>define_<action></tt> methods define performers for lifecycle
73
- # actions. Every action block must return boolean result, which
74
- # would mean the action success. If action performed unsuccessfully
75
- # Granite::Form::ObjectNotSaved or Granite::Form::ObjectNotDestroyed will
76
- # be raised respectively in case of bang methods using.
77
- #
78
- # class Author
79
- # define_create { true }
80
- # end
81
- #
82
- # Author.new.save # => true
83
- # Author.new.save! # => true
84
- #
85
- # class Author
86
- # define_create { false }
87
- # end
88
- #
89
- # Author.new.save # => false
90
- # Author.new.save! # => Granite::Form::ObjectNotSaved
91
- #
92
- # Also performers blocks are executed in the instance context, but
93
- # instance also passed as argument
94
- #
95
- # define_update do |instance|
96
- # instance.attributes.to_json
97
- # end
98
- #
99
- # +define_create+ and +define_update+ performers has higher priority
100
- # than +define_save+.
101
- #
102
- # class Author
103
- # define_update { ... }
104
- # define_save { ... }
105
- # end
106
- #
107
- # author = Author.create # using define_save performer
108
- # author.update_attributes(...) # using define_update performer
109
- #
110
- %i[save create update destroy].each do |action|
111
- define_method "define_#{action}" do |&block|
112
- send("_#{action}_performer=", block)
113
- end
114
- end
115
-
116
- # Initializes new instance with attributes passed and calls +save+
117
- # on it. Returns instance in any case.
118
- #
119
- def create(*args)
120
- new(*args).tap(&:save)
121
- end
122
-
123
- # Initializes new instance with attributes passed and calls +save!+
124
- # on it. Returns instance in case of success and raises Granite::Form::ValidationError
125
- # or Granite::Form::ObjectNotSaved in case of validation or saving fail respectively.
126
- #
127
- def create!(*args)
128
- new(*args).tap(&:save!)
129
- end
130
- end
131
-
132
- # <tt>define_<action></tt> on instance level works the same
133
- # way as class <tt>define_<action></tt> methods, but defines
134
- # performers for instance only
135
- #
136
- # user.define_save do
137
- # REDIS.set(id, attributes.to_json)
138
- # end
139
- # user.save! # => will use instance-level performer
140
- #
141
- %i[save create update destroy].each do |action|
142
- define_method "define_#{action}" do |&block|
143
- send("_#{action}_performer=", block)
144
- end
145
- end
146
-
147
- # Assigns passed attributes and calls +save+
148
- # Returns true or false in case of successful or unsuccessful
149
- # saving respectively.
150
- #
151
- # author.update(name: 'Donald')
152
- #
153
- # If update performer is not defined with `define_update`
154
- # or `define_save`, it raises Granite::Form::UnsavableObject.
155
- # Also save performer block might be passed instead of in-class
156
- # performer definition:
157
- #
158
- # author.update(name: 'Donald') { REDIS.set(id, attributes.to_json) }
159
- #
160
- def update(attributes, &block)
161
- assign_attributes(attributes) && save(&block)
162
- end
163
-
164
- alias_method :update_attributes, :update
165
-
166
- # Assigns passed attributes and calls +save!+
167
- # Returns true in case of success and raises Granite::Form::ValidationError
168
- # or Granite::Form::ObjectNotSaved in case of validation or
169
- # saving fail respectively.
170
- #
171
- # author.update!(name: 'Donald')
172
- #
173
- # If update performer is not defined with `define_update`
174
- # or `define_save`, it raises Granite::Form::UnsavableObject.
175
- # Also save performer block might be passed instead of in-class
176
- # performer definition:
177
- #
178
- # author.update!(name: 'Donald') { REDIS.set(id, attributes.to_json) }
179
- #
180
- def update!(attributes, &block)
181
- assign_attributes(attributes) && save!(&block)
182
- end
183
-
184
- alias_method :update_attributes!, :update!
185
-
186
- # # Saves object by calling save performer defined with +define_save+,
187
- # +define_create+ or +define_update+ methods.
188
- # Returns true or false in case of successful
189
- # or unsuccessful saving respectively. Changes +persisted?+ to true
190
- #
191
- # author.save
192
- #
193
- # If save performer is not defined with `define_update` or
194
- # `define_create` or `define_save`, it raises Granite::Form::UnsavableObject.
195
- # Also save performer block might be passed instead of in-class
196
- # performer definition:
197
- #
198
- # author.save { REDIS.set(id, attributes.to_json) }
199
- #
200
- def save(_options = {}, &block)
201
- raise Granite::Form::UnsavableObject unless block || savable?
202
- valid? && save_object(&block)
203
- end
204
-
205
- # Saves object by calling save performer defined with +define_save+,
206
- # +define_create+ or +define_update+ methods.
207
- # Returns true in case of success and raises Granite::Form::ValidationError
208
- # or Granite::Form::ObjectNotSaved in case of validation or
209
- # saving fail respectively. Changes +persisted?+ to true
210
- #
211
- # author.save!
212
- #
213
- # If save performer is not defined with `define_update` or
214
- # `define_create` or `define_save`, it raises Granite::Form::UnsavableObject.
215
- # Also save performer block might be passed instead of in-class
216
- # performer definition:
217
- #
218
- # author.save! { REDIS.set(id, attributes.to_json) }
219
- #
220
- def save!(_options = {}, &block)
221
- raise Granite::Form::UnsavableObject unless block || savable?
222
- validate!
223
- save_object(&block) or raise Granite::Form::ObjectNotSaved
224
- end
225
-
226
- # Destroys object by calling the destroy performer.
227
- # Returns instance in any case. Changes +persisted?+
228
- # to false and +destroyed?+ to true in case of success.
229
- #
230
- # author.destroy
231
- #
232
- # If destroy performer is not defined with `define_destroy`,
233
- # it raises Granite::Form::UndestroyableObject.
234
- # Also destroy performer block might be passed instead of in-class
235
- # performer definition:
236
- #
237
- # author.destroy { REDIS.del(id) }
238
- #
239
- def destroy(&block)
240
- raise Granite::Form::UndestroyableObject unless block || destroyable?
241
- destroy_object(&block)
242
- self
243
- end
244
-
245
- # Destroys object by calling the destroy performer.
246
- # In case of success returns instance and changes +persisted?+
247
- # to false and +destroyed?+ to true.
248
- # Raises Granite::Form::ObjectNotDestroyed in case of fail.
249
- #
250
- # author.destroy!
251
- #
252
- # If destroy performer is not defined with `define_destroy`,
253
- # it raises Granite::Form::UndestroyableObject.
254
- # Also destroy performer block might be passed instead of in-class
255
- # performer definition:
256
- #
257
- # author.destroy! { REDIS.del(id) }
258
- #
259
- def destroy!(&block)
260
- raise Granite::Form::UndestroyableObject unless block || destroyable?
261
- destroy_object(&block) or raise Granite::Form::ObjectNotDestroyed
262
- self
263
- end
264
-
265
- private
266
-
267
- def savable?
268
- !!((persisted? ? _update_performer : _create_performer) || _save_performer)
269
- end
270
-
271
- def save_object(&block)
272
- apply_association_changes! if respond_to?(:apply_association_changes!)
273
- result = persisted? ? update_object(&block) : create_object(&block)
274
- mark_persisted! if result
275
- result
276
- end
277
-
278
- def create_object(&block)
279
- performer = block || _create_performer || _save_performer
280
- !!performer_exec(&performer)
281
- end
282
-
283
- def update_object(&block)
284
- performer = block || _update_performer || _save_performer
285
- !!performer_exec(&performer)
286
- end
287
-
288
- def destroyable?
289
- !!_destroy_performer
290
- end
291
-
292
- def destroy_object(&block)
293
- performer = block || _destroy_performer
294
- result = !!performer_exec(&performer)
295
- mark_destroyed! if result
296
- result
297
- end
298
-
299
- def performer_exec(&block)
300
- if block.arity == 1
301
- yield(self)
302
- else
303
- instance_exec(&block)
304
- end
305
- end
306
- end
307
- end
308
- end
309
- end