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.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -2
- data/.github/workflows/{ci.yml → ruby.yml} +22 -4
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +3 -3
- data/Appraisals +1 -2
- data/CHANGELOG.md +7 -0
- data/README.md +0 -2
- data/docker-compose.yml +14 -0
- data/gemfiles/rails.5.0.gemfile +0 -1
- data/gemfiles/rails.5.1.gemfile +0 -1
- data/gemfiles/rails.5.2.gemfile +0 -1
- data/granite-form.gemspec +15 -15
- data/lib/granite/form/active_record/associations.rb +1 -1
- data/lib/granite/form/base.rb +1 -2
- data/lib/granite/form/errors.rb +0 -15
- data/lib/granite/form/model/associations/base.rb +0 -4
- data/lib/granite/form/model/associations/collection/embedded.rb +2 -1
- data/lib/granite/form/model/associations/collection/proxy.rb +1 -1
- data/lib/granite/form/model/associations/embeds_any.rb +7 -0
- data/lib/granite/form/model/associations/embeds_many.rb +9 -58
- data/lib/granite/form/model/associations/embeds_one.rb +7 -36
- data/lib/granite/form/model/associations/nested_attributes.rb +5 -5
- data/lib/granite/form/model/associations/persistence_adapters/active_record.rb +0 -4
- data/lib/granite/form/model/associations/persistence_adapters/base.rb +0 -4
- data/lib/granite/form/model/associations/references_many.rb +0 -32
- data/lib/granite/form/model/associations/references_one.rb +0 -28
- data/lib/granite/form/model/associations/reflections/embeds_any.rb +1 -1
- data/lib/granite/form/model/associations/reflections/references_any.rb +0 -4
- data/lib/granite/form/model/associations/reflections/references_one.rb +0 -2
- data/lib/granite/form/model/associations/reflections/singular.rb +0 -8
- data/lib/granite/form/model/associations.rb +0 -6
- data/lib/granite/form/model/attributes/base.rb +1 -1
- data/lib/granite/form/model/attributes/reflections/attribute.rb +0 -6
- data/lib/granite/form/model/attributes/reflections/base.rb +8 -7
- data/lib/granite/form/model/attributes/reflections/reference_one.rb +0 -6
- data/lib/granite/form/model/persistence.rb +1 -19
- data/lib/granite/form/model.rb +0 -2
- data/lib/granite/form/version.rb +1 -1
- data/spec/granite/form/active_record/associations_spec.rb +16 -18
- data/spec/granite/form/model/associations/embeds_many_spec.rb +29 -305
- data/spec/granite/form/model/associations/embeds_one_spec.rb +27 -212
- data/spec/granite/form/model/associations/nested_attributes_spec.rb +0 -95
- data/spec/granite/form/model/associations/references_many_spec.rb +5 -326
- data/spec/granite/form/model/associations/references_one_spec.rb +6 -278
- data/spec/granite/form/model/associations/reflections/embeds_any_spec.rb +1 -2
- data/spec/granite/form/model/associations/reflections/embeds_many_spec.rb +18 -26
- data/spec/granite/form/model/associations/reflections/embeds_one_spec.rb +16 -23
- data/spec/granite/form/model/associations/reflections/references_many_spec.rb +1 -1
- data/spec/granite/form/model/associations/reflections/references_one_spec.rb +1 -22
- data/spec/granite/form/model/associations/validations_spec.rb +0 -3
- data/spec/granite/form/model/associations_spec.rb +3 -24
- data/spec/granite/form/model/dirty_spec.rb +1 -1
- data/spec/granite/form/model/persistence_spec.rb +0 -2
- data/spec/granite/form/model/validations/associated_spec.rb +2 -4
- data/spec/granite/form/model/validations/nested_spec.rb +2 -4
- data/spec/spec_helper.rb +0 -15
- data/spec/support/active_record.rb +20 -0
- data/spec/support/shared/nested_attribute_examples.rb +3 -21
- metadata +32 -38
- data/.github/workflows/main.yml +0 -29
- data/gemfiles/rails.4.2.gemfile +0 -15
- data/lib/granite/form/model/callbacks.rb +0 -72
- data/lib/granite/form/model/lifecycle.rb +0 -309
- data/spec/granite/form/model/callbacks_spec.rb +0 -337
- 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.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Toptal Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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: '
|
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/
|
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
|
-
-
|
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:
|
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
|
data/.github/workflows/main.yml
DELETED
@@ -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
|
data/gemfiles/rails.4.2.gemfile
DELETED
@@ -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
|