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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 848ee19f938a86a22a506585a7a4960bbb192b977fdc61173b05057c0381ec79
|
4
|
+
data.tar.gz: 9c024906d4e6c7c8a93db7bcfe005dbffa956e4239a0078d642b3604c4226c0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e35f2d05bd0adaabdb00df1799b9997d6f01818f00271ee24cc628b9e5edf859ab4f15e1ee3e56f697485d89a2f1c05ebeff42816f53b4293c82854e3f4e247e
|
7
|
+
data.tar.gz: df23355e592e78a1d998ace8a8010e188360ce99173fe69623bf3b03da18286f3476d509620b89f91fcaa5df299a20b32906cb3c0ae95353b75eb2c694afe409
|
data/.github/CODEOWNERS
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
.github/workflows/main.yml @toptal/coresmiths-team
|
1
|
+
* @toptal/coresmiths-team
|
@@ -1,21 +1,39 @@
|
|
1
|
-
name:
|
2
|
-
on:
|
1
|
+
name: Ruby
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches: [ master ]
|
5
|
+
pull_request:
|
6
|
+
branches: [ master ]
|
3
7
|
jobs:
|
4
8
|
rspec:
|
5
9
|
strategy:
|
6
10
|
fail-fast: false
|
7
11
|
matrix:
|
8
12
|
include:
|
9
|
-
- { ruby: '2.3', rails: '4.2' }
|
10
13
|
- { ruby: '2.4', rails: '5.0' }
|
11
14
|
- { ruby: '2.5', rails: '5.1' }
|
12
15
|
- { ruby: '2.6', rails: '5.2' }
|
13
16
|
- { ruby: '2.7', rails: '6.0' }
|
14
17
|
- { ruby: '3.0', rails: '6.1' }
|
15
|
-
- { ruby: '3.
|
18
|
+
- { ruby: '3.1', rails: '7.0' }
|
16
19
|
runs-on: ubuntu-latest
|
17
20
|
env:
|
18
21
|
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails.${{ matrix.rails }}.gemfile
|
22
|
+
services:
|
23
|
+
postgres:
|
24
|
+
image: postgres
|
25
|
+
env:
|
26
|
+
POSTGRES_USER: granite
|
27
|
+
POSTGRES_PASSWORD: granite
|
28
|
+
# Set health checks to wait until postgres has started
|
29
|
+
options: >-
|
30
|
+
--health-cmd pg_isready
|
31
|
+
--health-interval 10s
|
32
|
+
--health-timeout 5s
|
33
|
+
--health-retries 5
|
34
|
+
ports:
|
35
|
+
# Maps tcp port 5432 on service container to the host
|
36
|
+
- 5432:5432
|
19
37
|
steps:
|
20
38
|
- uses: actions/checkout@v2
|
21
39
|
- uses: ruby/setup-ruby@v1
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
|
9
9
|
# Offense count: 19
|
10
10
|
Metrics/AbcSize:
|
11
|
-
Max:
|
11
|
+
Max: 59
|
12
12
|
|
13
13
|
# Offense count: 2
|
14
14
|
# Configuration parameters: CountComments.
|
@@ -17,7 +17,7 @@ Metrics/ClassLength:
|
|
17
17
|
|
18
18
|
# Offense count: 4
|
19
19
|
Metrics/CyclomaticComplexity:
|
20
|
-
Max:
|
20
|
+
Max: 15
|
21
21
|
|
22
22
|
# Offense count: 904
|
23
23
|
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives.
|
@@ -41,7 +41,7 @@ Metrics/BlockLength:
|
|
41
41
|
|
42
42
|
# Offense count: 4
|
43
43
|
Metrics/PerceivedComplexity:
|
44
|
-
Max:
|
44
|
+
Max: 18
|
45
45
|
|
46
46
|
# Offense count: 75
|
47
47
|
Style/Documentation:
|
data/Appraisals
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
%w[
|
1
|
+
%w[5.0 5.1 5.2 6.0 6.1 7.0].each do |version|
|
2
2
|
appraise "rails.#{version}" do
|
3
3
|
gem 'activesupport', "~> #{version}.0"
|
4
4
|
gem 'activemodel', "~> #{version}.0"
|
5
5
|
gem 'activerecord', "~> #{version}.0"
|
6
|
-
gem 'sqlite3', '~> 1.3.6' if version < '6.0'
|
7
6
|
end
|
8
7
|
end
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
# master
|
2
2
|
|
3
3
|
## Next
|
4
|
+
## v0.3.0
|
5
|
+
|
6
|
+
- [BREAKING] Stop automatically saving `references_one`/`references_many` when applying changes.
|
7
|
+
- [BREAKING] Removed Lifecycle module. `embeds_many`/`embeds_one` objects can no longer be created/saved/updated/destroyed.
|
8
|
+
- [BREAKING] Due to changes above `accepts_nested_attributes_for` for `embeds_many`/`embeds_one` associations no longer marks objects for destruction but simply removes them, making changes instantly.
|
9
|
+
- Drop support for ruby 2.3 and rails 4.2
|
10
|
+
|
4
11
|
## v0.2.0
|
5
12
|
|
6
13
|
- Replace typecasters with proper type definitions.
|
data/README.md
CHANGED
data/docker-compose.yml
ADDED
data/gemfiles/rails.5.0.gemfile
CHANGED
data/gemfiles/rails.5.1.gemfile
CHANGED
data/gemfiles/rails.5.2.gemfile
CHANGED
data/granite-form.gemspec
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
require File.expand_path('../lib/granite/form/version', __FILE__)
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
|
-
gem.authors
|
5
|
-
gem.
|
6
|
-
gem.
|
7
|
-
gem.
|
8
|
-
gem.homepage = ''
|
4
|
+
gem.authors = ['Toptal Engineering']
|
5
|
+
gem.description = 'Making object from any hash or hash array'
|
6
|
+
gem.summary = 'Working with hashes in AR style'
|
7
|
+
gem.homepage = 'https://github.com/toptal/granite-form'
|
9
8
|
|
10
|
-
gem.files
|
11
|
-
gem.executables
|
12
|
-
gem.test_files
|
13
|
-
gem.name
|
9
|
+
gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
10
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
11
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
12
|
+
gem.name = 'granite-form'
|
14
13
|
gem.require_paths = ['lib']
|
15
|
-
gem.
|
14
|
+
gem.required_ruby_version = '>= 2.4.0'
|
15
|
+
gem.version = Granite::Form::VERSION
|
16
16
|
|
17
|
-
gem.add_development_dependency 'actionpack', '>=
|
18
|
-
gem.add_development_dependency 'activerecord', '>=
|
17
|
+
gem.add_development_dependency 'actionpack', '>= 5.0'
|
18
|
+
gem.add_development_dependency 'activerecord', '>= 5.0'
|
19
19
|
gem.add_development_dependency 'appraisal'
|
20
20
|
gem.add_development_dependency 'bump'
|
21
21
|
gem.add_development_dependency 'database_cleaner'
|
22
|
+
gem.add_development_dependency 'pg'
|
22
23
|
gem.add_development_dependency 'rake'
|
23
24
|
gem.add_development_dependency 'rspec', '~> 3.7.0'
|
24
25
|
gem.add_development_dependency 'rspec-its'
|
25
26
|
gem.add_development_dependency 'rubocop', '0.52.1'
|
26
|
-
gem.add_development_dependency 'sqlite3'
|
27
27
|
gem.add_development_dependency 'uuidtools'
|
28
28
|
|
29
|
-
gem.add_runtime_dependency 'activemodel', '>=
|
30
|
-
gem.add_runtime_dependency 'activesupport', '>=
|
29
|
+
gem.add_runtime_dependency 'activemodel', '>= 5.0'
|
30
|
+
gem.add_runtime_dependency 'activesupport', '>= 5.0'
|
31
31
|
gem.add_runtime_dependency 'tzinfo'
|
32
32
|
end
|
data/lib/granite/form/base.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'granite/form/model'
|
2
2
|
require 'granite/form/model/primary'
|
3
|
-
require 'granite/form/model/lifecycle'
|
4
3
|
require 'granite/form/model/associations'
|
5
4
|
|
6
5
|
module Granite
|
@@ -8,7 +7,7 @@ module Granite
|
|
8
7
|
class Base
|
9
8
|
include Granite::Form::Model
|
10
9
|
include Granite::Form::Model::Primary
|
11
|
-
include Granite::Form::Model::
|
10
|
+
include Granite::Form::Model::Persistence
|
12
11
|
include Granite::Form::Model::Associations
|
13
12
|
end
|
14
13
|
end
|
data/lib/granite/form/errors.rb
CHANGED
@@ -17,21 +17,6 @@ module Granite
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
class UnsavableObject < Error
|
21
|
-
end
|
22
|
-
|
23
|
-
class UndestroyableObject < Error
|
24
|
-
end
|
25
|
-
|
26
|
-
class ObjectNotSaved < Error
|
27
|
-
end
|
28
|
-
|
29
|
-
class ObjectNotDestroyed < Error
|
30
|
-
end
|
31
|
-
|
32
|
-
class AssociationChangesNotApplied < Error
|
33
|
-
end
|
34
|
-
|
35
20
|
class AssociationTypeMismatch < Error
|
36
21
|
def initialize(expected, got)
|
37
22
|
super "Expected `#{expected}` (##{expected.object_id}), but got `#{got}` (##{got.object_id})"
|
@@ -6,7 +6,7 @@ module Granite
|
|
6
6
|
class Proxy
|
7
7
|
include Enumerable
|
8
8
|
|
9
|
-
delegate :target, :
|
9
|
+
delegate :target, :loaded?, :reload, :clear, :concat, to: :@association
|
10
10
|
delegate :each, :size, :length, :first, :last, :empty?, :many?, :==, :dup, to: :target
|
11
11
|
alias_method :<<, :concat
|
12
12
|
alias_method :push, :concat
|
@@ -12,6 +12,13 @@ module Granite
|
|
12
12
|
def embed_object(object)
|
13
13
|
object.instance_variable_set(:@embedder, owner)
|
14
14
|
end
|
15
|
+
|
16
|
+
def model_data(model)
|
17
|
+
return unless model
|
18
|
+
|
19
|
+
model.association_names.each { |assoc_name| model.association(assoc_name).sync }
|
20
|
+
model.attributes
|
21
|
+
end
|
15
22
|
end
|
16
23
|
end
|
17
24
|
end
|
@@ -7,27 +7,6 @@ module Granite
|
|
7
7
|
push_object(build_object(attributes))
|
8
8
|
end
|
9
9
|
|
10
|
-
def create(attributes = {})
|
11
|
-
build(attributes).tap(&:save)
|
12
|
-
end
|
13
|
-
|
14
|
-
def create!(attributes = {})
|
15
|
-
build(attributes).tap(&:save!)
|
16
|
-
end
|
17
|
-
|
18
|
-
def destroyed
|
19
|
-
@destroyed ||= []
|
20
|
-
end
|
21
|
-
|
22
|
-
def apply_changes
|
23
|
-
result = target.map do |object|
|
24
|
-
object.destroyed? || object.marked_for_destruction? ? object.destroy : object.save
|
25
|
-
end.all?
|
26
|
-
@destroyed = target.select(&:destroyed?)
|
27
|
-
target.delete_if(&:destroyed?)
|
28
|
-
result
|
29
|
-
end
|
30
|
-
|
31
10
|
def target=(objects)
|
32
11
|
objects.each { |object| setup_performers! object }
|
33
12
|
loaded!
|
@@ -63,13 +42,14 @@ module Granite
|
|
63
42
|
@target = []
|
64
43
|
end
|
65
44
|
|
45
|
+
def sync
|
46
|
+
write_source(target.map { |model| model_data(model) })
|
47
|
+
end
|
48
|
+
|
66
49
|
def clear
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
nil
|
71
|
-
end
|
72
|
-
reload.empty?
|
50
|
+
target
|
51
|
+
@target = []
|
52
|
+
true
|
73
53
|
end
|
74
54
|
|
75
55
|
def reader(force_reload = false)
|
@@ -80,7 +60,7 @@ module Granite
|
|
80
60
|
def replace(objects)
|
81
61
|
transaction do
|
82
62
|
clear
|
83
|
-
append(objects)
|
63
|
+
append(objects)
|
84
64
|
end
|
85
65
|
end
|
86
66
|
|
@@ -101,8 +81,7 @@ module Granite
|
|
101
81
|
raise AssociationTypeMismatch.new(reflection.klass, object.class) unless object && object.is_a?(reflection.klass)
|
102
82
|
push_object object
|
103
83
|
end
|
104
|
-
|
105
|
-
result && target
|
84
|
+
target
|
106
85
|
end
|
107
86
|
|
108
87
|
def push_object(object)
|
@@ -115,34 +94,6 @@ module Granite
|
|
115
94
|
embed_object(object)
|
116
95
|
callback(:before_add, object)
|
117
96
|
|
118
|
-
association = self
|
119
|
-
|
120
|
-
object.define_create do
|
121
|
-
source = association.send(:read_source)
|
122
|
-
index = association.target
|
123
|
-
.select { |one| one.persisted? || one.equal?(self) }
|
124
|
-
.index { |one| one.equal?(self) }
|
125
|
-
|
126
|
-
source.insert(index, attributes)
|
127
|
-
association.send(:write_source, source)
|
128
|
-
end
|
129
|
-
|
130
|
-
object.define_update do
|
131
|
-
source = association.send(:read_source)
|
132
|
-
index = association.target.select(&:persisted?).index { |one| one.equal?(self) }
|
133
|
-
|
134
|
-
source[index] = attributes
|
135
|
-
association.send(:write_source, source)
|
136
|
-
end
|
137
|
-
|
138
|
-
object.define_destroy do
|
139
|
-
source = association.send(:read_source)
|
140
|
-
index = association.target.select(&:persisted?).index { |one| one.equal?(self) }
|
141
|
-
|
142
|
-
source.delete_at(index) if index
|
143
|
-
association.send(:write_source, source)
|
144
|
-
end
|
145
|
-
|
146
97
|
callback(:after_add, object)
|
147
98
|
end
|
148
99
|
end
|
@@ -3,33 +3,10 @@ module Granite
|
|
3
3
|
module Model
|
4
4
|
module Associations
|
5
5
|
class EmbedsOne < EmbedsAny
|
6
|
-
attr_reader :destroyed
|
7
|
-
|
8
6
|
def build(attributes = {})
|
9
7
|
self.target = build_object(attributes)
|
10
8
|
end
|
11
9
|
|
12
|
-
def create(attributes = {})
|
13
|
-
build(attributes).tap(&:save)
|
14
|
-
end
|
15
|
-
|
16
|
-
def create!(attributes = {})
|
17
|
-
build(attributes).tap(&:save!)
|
18
|
-
end
|
19
|
-
|
20
|
-
def apply_changes
|
21
|
-
if target
|
22
|
-
if target.destroyed? || target.marked_for_destruction?
|
23
|
-
@destroyed = target
|
24
|
-
clear
|
25
|
-
else
|
26
|
-
target.save
|
27
|
-
end
|
28
|
-
else
|
29
|
-
true
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
10
|
def target=(object)
|
34
11
|
if object
|
35
12
|
callback(:before_add, object)
|
@@ -63,9 +40,14 @@ module Granite
|
|
63
40
|
object
|
64
41
|
end
|
65
42
|
|
43
|
+
def sync
|
44
|
+
write_source(model_data(target))
|
45
|
+
end
|
46
|
+
|
66
47
|
def clear
|
67
|
-
target
|
68
|
-
|
48
|
+
target
|
49
|
+
@target = nil
|
50
|
+
true
|
69
51
|
end
|
70
52
|
|
71
53
|
def reader(force_reload = false)
|
@@ -79,7 +61,6 @@ module Granite
|
|
79
61
|
transaction do
|
80
62
|
clear
|
81
63
|
self.target = object
|
82
|
-
apply_changes! if owner.persisted?
|
83
64
|
end
|
84
65
|
else
|
85
66
|
clear
|
@@ -94,16 +75,6 @@ module Granite
|
|
94
75
|
|
95
76
|
def setup_performers!(object)
|
96
77
|
embed_object(object)
|
97
|
-
association = self
|
98
|
-
|
99
|
-
object.define_save do
|
100
|
-
association.send(:write_source, attributes)
|
101
|
-
end
|
102
|
-
|
103
|
-
object.define_destroy do
|
104
|
-
association.send(:write_source, nil)
|
105
|
-
true
|
106
|
-
end
|
107
78
|
end
|
108
79
|
end
|
109
80
|
end
|
@@ -78,7 +78,8 @@ module Granite
|
|
78
78
|
end
|
79
79
|
|
80
80
|
if existing_record && (!primary_attribute || options[:update_only] || existing_record.primary_attribute == primary_attribute_value)
|
81
|
-
|
81
|
+
assign_to(existing_record, attributes) unless call_reject_if(object, association_name, attributes)
|
82
|
+
association.clear if destroy_flag?(attributes) && options[:allow_destroy]
|
82
83
|
elsif attributes[primary_attribute_name].present?
|
83
84
|
raise Granite::Form::ObjectNotFound.new(object, association_name, attributes[primary_attribute_name])
|
84
85
|
elsif !reject_new_object?(object, association_name, attributes, options)
|
@@ -127,7 +128,8 @@ module Granite
|
|
127
128
|
record.primary_attribute == primary_attribute_value
|
128
129
|
end
|
129
130
|
if existing_record
|
130
|
-
|
131
|
+
assign_to(existing_record, attributes) unless call_reject_if(object, association_name, attributes)
|
132
|
+
association.target.delete(existing_record) if destroy_flag?(attributes) && options[:allow_destroy]
|
131
133
|
elsif association.reflection.embedded?
|
132
134
|
unless reject_new_object?(object, association_name, attributes, options)
|
133
135
|
association.reflection.klass.with_sanitize(false) do
|
@@ -156,9 +158,8 @@ module Granite
|
|
156
158
|
raise Granite::Form::TooManyObjects.new(limit, attributes_collection.size)
|
157
159
|
end
|
158
160
|
|
159
|
-
def self.
|
161
|
+
def self.assign_to(object, attributes)
|
160
162
|
object.assign_attributes(attributes.except(*unassignable_keys(object)))
|
161
|
-
object.mark_for_destruction if destroy_flag?(attributes) && allow_destroy
|
162
163
|
end
|
163
164
|
|
164
165
|
def self.destroy_flag?(hash)
|
@@ -170,7 +171,6 @@ module Granite
|
|
170
171
|
end
|
171
172
|
|
172
173
|
def self.call_reject_if(object, association_name, attributes)
|
173
|
-
return false if destroy_flag?(attributes)
|
174
174
|
case callback = object.nested_attributes_options[association_name][:reject_if]
|
175
175
|
when Symbol
|
176
176
|
method(callback).arity.zero? ? send(callback) : send(callback, attributes)
|
@@ -16,10 +16,6 @@ module Granite
|
|
16
16
|
raise NotImplementedError, 'Should be implemented in inhereted adapter. Build new instance of data object by attributes'
|
17
17
|
end
|
18
18
|
|
19
|
-
def persist(_object, *)
|
20
|
-
raise NotImplementedError, 'Should be implemented in inhereted adapter. Build new instance of data object by attributes'
|
21
|
-
end
|
22
|
-
|
23
19
|
def scope(_owner, _source)
|
24
20
|
raise NotImplementedError, 'Should be implemented in inhereted adapter. Better to be Enumerable'
|
25
21
|
end
|
@@ -3,38 +3,6 @@ module Granite
|
|
3
3
|
module Model
|
4
4
|
module Associations
|
5
5
|
class ReferencesMany < ReferencesAny
|
6
|
-
def build(attributes = {})
|
7
|
-
append([build_object(attributes)]).last
|
8
|
-
end
|
9
|
-
|
10
|
-
def create(attributes = {})
|
11
|
-
object = build(attributes)
|
12
|
-
persist_object(object)
|
13
|
-
object
|
14
|
-
end
|
15
|
-
|
16
|
-
def create!(attributes = {})
|
17
|
-
object = build(attributes)
|
18
|
-
persist_object(object, raise_error: true)
|
19
|
-
object
|
20
|
-
end
|
21
|
-
|
22
|
-
def apply_changes
|
23
|
-
target.all? do |object|
|
24
|
-
if object
|
25
|
-
if object.marked_for_destruction? && reflection.autosave?
|
26
|
-
object.destroy
|
27
|
-
elsif object.new_record? || (reflection.autosave? && object.changed?)
|
28
|
-
persist_object(object)
|
29
|
-
else
|
30
|
-
true
|
31
|
-
end
|
32
|
-
else
|
33
|
-
true
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
6
|
def target=(object)
|
39
7
|
loaded!
|
40
8
|
@target = object.to_a
|
@@ -3,34 +3,6 @@ module Granite
|
|
3
3
|
module Model
|
4
4
|
module Associations
|
5
5
|
class ReferencesOne < ReferencesAny
|
6
|
-
def build(attributes = {})
|
7
|
-
replace(build_object(attributes))
|
8
|
-
end
|
9
|
-
|
10
|
-
def create(attributes = {})
|
11
|
-
persist_object(build(attributes))
|
12
|
-
target
|
13
|
-
end
|
14
|
-
|
15
|
-
def create!(attributes = {})
|
16
|
-
persist_object(build(attributes), raise_error: true)
|
17
|
-
target
|
18
|
-
end
|
19
|
-
|
20
|
-
def apply_changes
|
21
|
-
if target
|
22
|
-
if target.marked_for_destruction? && reflection.autosave?
|
23
|
-
target.destroy
|
24
|
-
elsif target.new_record? || (reflection.autosave? && target.changed?)
|
25
|
-
persist_object(target)
|
26
|
-
else
|
27
|
-
true
|
28
|
-
end
|
29
|
-
else
|
30
|
-
true
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
6
|
def target=(object)
|
35
7
|
loaded!
|
36
8
|
@target = object
|
@@ -22,7 +22,7 @@ module Granite
|
|
22
22
|
Class.new(superclass || Granite::Form.base_class) do
|
23
23
|
include Granite::Form::Model
|
24
24
|
include Granite::Form::Model::Associations
|
25
|
-
include Granite::Form::Model::
|
25
|
+
include Granite::Form::Model::Persistence
|
26
26
|
include Granite::Form::Model::Primary
|
27
27
|
include Granite::Form.base_concern if Granite::Form.base_concern
|
28
28
|
end
|