active_data 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +13 -0
- data/.rubocop.yml +56 -0
- data/.rubocop_todo.yml +53 -0
- data/.rvmrc +1 -1
- data/.travis.yml +15 -2
- data/Appraisals +1 -1
- data/CHANGELOG.md +31 -0
- data/Guardfile +8 -8
- data/README.md +256 -0
- data/Rakefile +2 -4
- data/active_data.gemspec +8 -7
- data/gemfiles/rails.4.0.gemfile +1 -1
- data/gemfiles/rails.4.1.gemfile +1 -1
- data/gemfiles/rails.4.2.gemfile +1 -1
- data/gemfiles/rails.5.0.gemfile +1 -1
- data/gemfiles/rails.5.1.gemfile +14 -0
- data/lib/active_data/active_record/associations.rb +18 -13
- data/lib/active_data/active_record/nested_attributes.rb +8 -14
- data/lib/active_data/base.rb +13 -0
- data/lib/active_data/config.rb +4 -4
- data/lib/active_data/errors.rb +29 -13
- data/lib/active_data/extensions.rb +22 -21
- data/lib/active_data/model/associations/base.rb +22 -6
- data/lib/active_data/model/associations/embeds_any.rb +17 -0
- data/lib/active_data/model/associations/embeds_many.rb +29 -19
- data/lib/active_data/model/associations/embeds_one.rb +30 -26
- data/lib/active_data/model/associations/nested_attributes.rb +82 -50
- data/lib/active_data/model/associations/persistence_adapters/active_record/referenced_proxy.rb +31 -0
- data/lib/active_data/model/associations/persistence_adapters/active_record.rb +66 -0
- data/lib/active_data/model/associations/persistence_adapters/base.rb +53 -0
- data/lib/active_data/model/associations/references_any.rb +41 -0
- data/lib/active_data/model/associations/references_many.rb +51 -37
- data/lib/active_data/model/associations/references_one.rb +43 -41
- data/lib/active_data/model/associations/reflections/base.rb +19 -29
- data/lib/active_data/model/associations/reflections/embeds_any.rb +43 -0
- data/lib/active_data/model/associations/reflections/embeds_many.rb +3 -13
- data/lib/active_data/model/associations/reflections/embeds_one.rb +5 -37
- data/lib/active_data/model/associations/reflections/references_any.rb +62 -0
- data/lib/active_data/model/associations/reflections/references_many.rb +7 -7
- data/lib/active_data/model/associations/reflections/references_one.rb +9 -7
- data/lib/active_data/model/associations/reflections/singular.rb +35 -0
- data/lib/active_data/model/associations/validations.rb +2 -27
- data/lib/active_data/model/associations.rb +12 -10
- data/lib/active_data/model/attributes/attribute.rb +10 -10
- data/lib/active_data/model/attributes/base.rb +8 -7
- data/lib/active_data/model/attributes/localized.rb +4 -4
- data/lib/active_data/model/attributes/reference_many.rb +6 -8
- data/lib/active_data/model/attributes/reference_one.rb +17 -9
- data/lib/active_data/model/attributes/reflections/attribute.rb +2 -2
- data/lib/active_data/model/attributes/reflections/base.rb +8 -11
- data/lib/active_data/model/attributes/reflections/localized.rb +2 -2
- data/lib/active_data/model/attributes/reflections/reference_one.rb +11 -22
- data/lib/active_data/model/attributes/reflections/represents.rb +5 -6
- data/lib/active_data/model/attributes/represents.rb +6 -5
- data/lib/active_data/model/attributes.rb +33 -87
- data/lib/active_data/model/callbacks.rb +6 -7
- data/lib/active_data/model/conventions.rb +2 -0
- data/lib/active_data/model/dirty.rb +4 -4
- data/lib/active_data/model/lifecycle.rb +18 -20
- data/lib/active_data/model/localization.rb +5 -2
- data/lib/active_data/model/persistence.rb +2 -2
- data/lib/active_data/model/primary.rb +19 -14
- data/lib/active_data/model/representation.rb +81 -0
- data/lib/active_data/model/scopes.rb +22 -12
- data/lib/active_data/model/validations/associated.rb +3 -2
- data/lib/active_data/model/validations/nested.rb +6 -1
- data/lib/active_data/model/validations.rb +3 -3
- data/lib/active_data/model.rb +2 -1
- data/lib/active_data/undefined_class.rb +9 -0
- data/lib/active_data/version.rb +1 -1
- data/lib/active_data.rb +40 -17
- data/spec/lib/active_data/active_record/associations_spec.rb +107 -45
- data/spec/lib/active_data/active_record/nested_attributes_spec.rb +1 -2
- data/spec/lib/active_data/config_spec.rb +37 -15
- data/spec/lib/active_data/model/associations/embeds_many_spec.rb +475 -172
- data/spec/lib/active_data/model/associations/embeds_one_spec.rb +353 -96
- data/spec/lib/active_data/model/associations/nested_attributes_spec.rb +108 -12
- data/spec/lib/active_data/model/associations/persistence_adapters/active_record_spec.rb +58 -0
- data/spec/lib/active_data/model/associations/references_many_spec.rb +440 -64
- data/spec/lib/active_data/model/associations/references_one_spec.rb +347 -36
- data/spec/lib/active_data/model/associations/reflections/embeds_many_spec.rb +8 -7
- data/spec/lib/active_data/model/associations/reflections/embeds_one_spec.rb +7 -6
- data/spec/lib/active_data/model/associations/reflections/references_many_spec.rb +81 -33
- data/spec/lib/active_data/model/associations/reflections/references_one_spec.rb +116 -37
- data/spec/lib/active_data/model/associations/validations_spec.rb +27 -43
- data/spec/lib/active_data/model/associations_spec.rb +34 -25
- data/spec/lib/active_data/model/attributes/attribute_spec.rb +26 -23
- data/spec/lib/active_data/model/attributes/base_spec.rb +5 -6
- data/spec/lib/active_data/model/attributes/collection_spec.rb +7 -8
- data/spec/lib/active_data/model/attributes/dictionary_spec.rb +40 -33
- data/spec/lib/active_data/model/attributes/localized_spec.rb +27 -28
- data/spec/lib/active_data/model/attributes/reflections/attribute_spec.rb +6 -6
- data/spec/lib/active_data/model/attributes/represents_spec.rb +10 -78
- data/spec/lib/active_data/model/attributes_spec.rb +150 -45
- data/spec/lib/active_data/model/callbacks_spec.rb +69 -70
- data/spec/lib/active_data/model/conventions_spec.rb +0 -1
- data/spec/lib/active_data/model/dirty_spec.rb +22 -13
- data/spec/lib/active_data/model/lifecycle_spec.rb +49 -23
- data/spec/lib/active_data/model/persistence_spec.rb +5 -6
- data/spec/lib/active_data/model/representation_spec.rb +126 -0
- data/spec/lib/active_data/model/scopes_spec.rb +1 -3
- data/spec/lib/active_data/model/typecasting_spec.rb +6 -5
- data/spec/lib/active_data/model/validations/associated_spec.rb +26 -18
- data/spec/lib/active_data/model/validations/nested_spec.rb +89 -18
- data/spec/lib/active_data/model_spec.rb +1 -2
- data/spec/lib/active_data_spec.rb +0 -1
- data/spec/shared/nested_attribute_examples.rb +332 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/model_helpers.rb +2 -2
- data/spec/support/muffle_helper.rb +7 -0
- metadata +52 -18
- data/lib/active_data/model/associations/collection/referenced.rb +0 -26
- data/lib/active_data/model/associations/reflections/reference_reflection.rb +0 -45
- data/spec/lib/active_data/model/nested_attributes.rb +0 -202
@@ -11,27 +11,17 @@ module ActiveData
|
|
11
11
|
attr_accessor :parent_reflection
|
12
12
|
delegate :association_class, to: 'self.class'
|
13
13
|
|
14
|
-
def self.build
|
15
|
-
if block
|
16
|
-
options[:class] = proc do |reflection|
|
17
|
-
superclass = reflection.options[:class_name].to_s.presence.try(:constantize)
|
18
|
-
klass = Class.new(superclass || Object) do
|
19
|
-
include ActiveData::Model
|
20
|
-
include ActiveData::Model::Associations
|
21
|
-
include ActiveData::Model::Lifecycle
|
22
|
-
include ActiveData::Model::Primary
|
23
|
-
end
|
24
|
-
target.const_set(name.to_s.classify, klass)
|
25
|
-
klass.class_eval(&block)
|
26
|
-
klass
|
27
|
-
end
|
28
|
-
end
|
14
|
+
def self.build(target, generated_methods, name, options = {}, &_block)
|
29
15
|
generate_methods name, generated_methods
|
30
|
-
|
16
|
+
if options.delete(:validate) &&
|
17
|
+
target.respond_to?(:validates_nested) &&
|
18
|
+
!target.validates_nested?(name)
|
19
|
+
target.validates_nested name
|
20
|
+
end
|
31
21
|
new(name, options)
|
32
22
|
end
|
33
23
|
|
34
|
-
def self.generate_methods
|
24
|
+
def self.generate_methods(name, target)
|
35
25
|
target.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
36
26
|
def #{name} force_reload = false
|
37
27
|
association(:#{name}).reader(force_reload)
|
@@ -47,8 +37,9 @@ module ActiveData
|
|
47
37
|
@association_class ||= "ActiveData::Model::Associations::#{name.demodulize}".constantize
|
48
38
|
end
|
49
39
|
|
50
|
-
def initialize
|
51
|
-
@name
|
40
|
+
def initialize(name, options = {})
|
41
|
+
@name = name.to_sym
|
42
|
+
@options = options
|
52
43
|
end
|
53
44
|
|
54
45
|
def macro
|
@@ -56,31 +47,30 @@ module ActiveData
|
|
56
47
|
end
|
57
48
|
|
58
49
|
def klass
|
59
|
-
@klass ||= options[:
|
60
|
-
options[:class].call(self) :
|
61
|
-
(options[:class_name].presence || name.to_s.classify).to_s.constantize
|
50
|
+
@klass ||= (options[:class_name].presence || name.to_s.classify).to_s.constantize
|
62
51
|
end
|
63
52
|
|
53
|
+
# AR compatibility
|
64
54
|
def belongs_to?
|
65
55
|
false
|
66
56
|
end
|
67
57
|
|
68
|
-
def build_association
|
58
|
+
def build_association(object)
|
69
59
|
self.class.association_class.new object, self
|
70
60
|
end
|
71
61
|
|
72
|
-
def read_source
|
62
|
+
def read_source(object)
|
73
63
|
(options[:read] || READ).call(self, object)
|
74
64
|
end
|
75
65
|
|
76
|
-
def write_source
|
66
|
+
def write_source(object, value)
|
77
67
|
(options[:write] || WRITE).call(self, object, value)
|
78
68
|
end
|
79
69
|
|
80
|
-
def default
|
70
|
+
def default(object)
|
81
71
|
defaultizer = options[:default]
|
82
72
|
if defaultizer.is_a?(Proc)
|
83
|
-
if defaultizer.arity
|
73
|
+
if defaultizer.arity.nonzero?
|
84
74
|
defaultizer.call(object)
|
85
75
|
else
|
86
76
|
object.instance_exec(&defaultizer)
|
@@ -90,8 +80,8 @@ module ActiveData
|
|
90
80
|
end
|
91
81
|
end
|
92
82
|
|
93
|
-
def
|
94
|
-
|
83
|
+
def collection?
|
84
|
+
true
|
95
85
|
end
|
96
86
|
end
|
97
87
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ActiveData
|
2
|
+
module Model
|
3
|
+
module Associations
|
4
|
+
module Reflections
|
5
|
+
class EmbedsAny < Base
|
6
|
+
def self.build(target, generated_methods, name, options = {}, &block)
|
7
|
+
if block
|
8
|
+
options[:class] = proc do |reflection|
|
9
|
+
superclass = reflection.options[:class_name].to_s.presence.try(:constantize)
|
10
|
+
klass = Class.new(superclass || ActiveData::Base) do
|
11
|
+
include ActiveData::Model
|
12
|
+
include ActiveData::Model::Associations
|
13
|
+
include ActiveData::Model::Lifecycle
|
14
|
+
include ActiveData::Model::Primary
|
15
|
+
end
|
16
|
+
target.const_set(name.to_s.classify, klass)
|
17
|
+
klass.class_eval(&block)
|
18
|
+
klass
|
19
|
+
end
|
20
|
+
end
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def klass
|
25
|
+
@klass ||= if options[:class]
|
26
|
+
options[:class].call(self)
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def inspect
|
33
|
+
"#{self.class.name.demodulize}(#{klass})"
|
34
|
+
end
|
35
|
+
|
36
|
+
def embedded?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -2,22 +2,12 @@ module ActiveData
|
|
2
2
|
module Model
|
3
3
|
module Associations
|
4
4
|
module Reflections
|
5
|
-
class EmbedsMany <
|
6
|
-
def self.build
|
7
|
-
if target < ActiveData::Model::Attributes
|
8
|
-
target.add_attribute(ActiveData::Model::Attributes::Reflections::Base, name)
|
9
|
-
end
|
5
|
+
class EmbedsMany < EmbedsAny
|
6
|
+
def self.build(target, generated_methods, name, options = {}, &block)
|
7
|
+
target.add_attribute(ActiveData::Model::Attributes::Reflections::Base, name) if target < ActiveData::Model::Attributes
|
10
8
|
options[:validate] = true unless options.key?(:validate)
|
11
9
|
super
|
12
10
|
end
|
13
|
-
|
14
|
-
def collection?
|
15
|
-
true
|
16
|
-
end
|
17
|
-
|
18
|
-
def embedded?
|
19
|
-
true
|
20
|
-
end
|
21
11
|
end
|
22
12
|
end
|
23
13
|
end
|
@@ -2,46 +2,14 @@ module ActiveData
|
|
2
2
|
module Model
|
3
3
|
module Associations
|
4
4
|
module Reflections
|
5
|
-
class EmbedsOne <
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
class EmbedsOne < EmbedsAny
|
6
|
+
include Singular
|
7
|
+
|
8
|
+
def self.build(target, generated_methods, name, options = {}, &block)
|
9
|
+
target.add_attribute(ActiveData::Model::Attributes::Reflections::Base, name) if target < ActiveData::Model::Attributes
|
10
10
|
options[:validate] = true unless options.key?(:validate)
|
11
11
|
super
|
12
12
|
end
|
13
|
-
|
14
|
-
def self.generate_methods name, target
|
15
|
-
target.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
16
|
-
def #{name} force_reload = false
|
17
|
-
association(:#{name}).reader(force_reload)
|
18
|
-
end
|
19
|
-
|
20
|
-
def #{name}= value
|
21
|
-
association(:#{name}).writer(value)
|
22
|
-
end
|
23
|
-
|
24
|
-
def build_#{name} attributes = {}
|
25
|
-
association(:#{name}).build(attributes)
|
26
|
-
end
|
27
|
-
|
28
|
-
def create_#{name} attributes = {}
|
29
|
-
association(:#{name}).create(attributes)
|
30
|
-
end
|
31
|
-
|
32
|
-
def create_#{name}! attributes = {}
|
33
|
-
association(:#{name}).create!(attributes)
|
34
|
-
end
|
35
|
-
RUBY
|
36
|
-
end
|
37
|
-
|
38
|
-
def collection?
|
39
|
-
false
|
40
|
-
end
|
41
|
-
|
42
|
-
def embedded?
|
43
|
-
true
|
44
|
-
end
|
45
13
|
end
|
46
14
|
end
|
47
15
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ActiveData
|
2
|
+
module Model
|
3
|
+
module Associations
|
4
|
+
module Reflections
|
5
|
+
class ReferencesAny < Base
|
6
|
+
def self.build(_target, generated_methods, name, *args)
|
7
|
+
reflection = new(name, *args)
|
8
|
+
generate_methods name, generated_methods
|
9
|
+
reflection
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.persistence_adapter(klass)
|
13
|
+
adapter = klass.active_data_persistence_adapter if klass.respond_to?(:active_data_persistence_adapter)
|
14
|
+
adapter or raise PersistenceAdapterMissing, klass
|
15
|
+
end
|
16
|
+
|
17
|
+
delegate :primary_key, to: :persistence_adapter
|
18
|
+
|
19
|
+
def initialize(name, *args)
|
20
|
+
@options = args.extract_options!
|
21
|
+
@scope_proc = args.first
|
22
|
+
@name = name.to_sym
|
23
|
+
end
|
24
|
+
|
25
|
+
def klass
|
26
|
+
@klass ||= if options[:data_source].present?
|
27
|
+
options[:data_source].to_s.constantize
|
28
|
+
else
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
alias_method :data_source, :klass
|
33
|
+
|
34
|
+
def persistence_adapter
|
35
|
+
@persistence_adapter ||= self.class.persistence_adapter(klass)
|
36
|
+
.new(data_source, options[:primary_key], @scope_proc)
|
37
|
+
end
|
38
|
+
|
39
|
+
def read_source(object)
|
40
|
+
object.read_attribute(reference_key)
|
41
|
+
end
|
42
|
+
|
43
|
+
def write_source(object, value)
|
44
|
+
object.write_attribute(reference_key, value)
|
45
|
+
end
|
46
|
+
|
47
|
+
def embedded?
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def inspect
|
52
|
+
"#{self.class.name.demodulize}(#{persistence_adapter.data_type})"
|
53
|
+
end
|
54
|
+
|
55
|
+
def autosave?
|
56
|
+
!!options[:autosave]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -1,22 +1,22 @@
|
|
1
|
+
require 'active_data/model/attributes/reflections/reference_many'
|
2
|
+
require 'active_data/model/attributes/reference_many'
|
3
|
+
|
1
4
|
module ActiveData
|
2
5
|
module Model
|
3
6
|
module Associations
|
4
7
|
module Reflections
|
5
|
-
class ReferencesMany <
|
6
|
-
def self.build
|
8
|
+
class ReferencesMany < ReferencesAny
|
9
|
+
def self.build(target, generated_methods, name, *args, &block)
|
7
10
|
reflection = super
|
8
11
|
|
9
12
|
target.add_attribute(
|
10
13
|
ActiveData::Model::Attributes::Reflections::ReferenceMany,
|
11
|
-
reflection.reference_key, association: name
|
14
|
+
reflection.reference_key, association: name
|
15
|
+
)
|
12
16
|
|
13
17
|
reflection
|
14
18
|
end
|
15
19
|
|
16
|
-
def collection?
|
17
|
-
true
|
18
|
-
end
|
19
|
-
|
20
20
|
def reference_key
|
21
21
|
@reference_key ||= options[:reference_key].presence.try(:to_sym) ||
|
22
22
|
:"#{name.to_s.singularize}_#{primary_key.to_s.pluralize}"
|
@@ -1,22 +1,24 @@
|
|
1
|
+
require 'active_data/model/attributes/reflections/reference_one'
|
2
|
+
require 'active_data/model/attributes/reference_one'
|
3
|
+
|
1
4
|
module ActiveData
|
2
5
|
module Model
|
3
6
|
module Associations
|
4
7
|
module Reflections
|
5
|
-
class ReferencesOne <
|
6
|
-
|
8
|
+
class ReferencesOne < ReferencesAny
|
9
|
+
include Singular
|
10
|
+
|
11
|
+
def self.build(target, generated_methods, name, *args, &block)
|
7
12
|
reflection = super
|
8
13
|
|
9
14
|
target.add_attribute(
|
10
15
|
ActiveData::Model::Attributes::Reflections::ReferenceOne,
|
11
|
-
reflection.reference_key, association: name
|
16
|
+
reflection.reference_key, association: name
|
17
|
+
)
|
12
18
|
|
13
19
|
reflection
|
14
20
|
end
|
15
21
|
|
16
|
-
def collection?
|
17
|
-
false
|
18
|
-
end
|
19
|
-
|
20
22
|
def reference_key
|
21
23
|
@reference_key ||= options[:reference_key].presence.try(:to_sym) ||
|
22
24
|
:"#{name}_#{primary_key}"
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ActiveData
|
2
|
+
module Model
|
3
|
+
module Associations
|
4
|
+
module Reflections
|
5
|
+
module Singular
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def generate_methods(name, target)
|
10
|
+
super
|
11
|
+
|
12
|
+
target.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
13
|
+
def build_#{name} attributes = {}
|
14
|
+
association(:#{name}).build(attributes)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_#{name} attributes = {}
|
18
|
+
association(:#{name}).create(attributes)
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_#{name}! attributes = {}
|
22
|
+
association(:#{name}).create!(attributes)
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def collection?
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -19,44 +19,19 @@ module ActiveData
|
|
19
19
|
|
20
20
|
private
|
21
21
|
|
22
|
-
def run_validations! #:nodoc:
|
23
|
-
super
|
24
|
-
emerge_represented_attributes_errors!
|
25
|
-
errors.empty?
|
26
|
-
end
|
27
|
-
|
28
22
|
def validate_nested!
|
29
23
|
association_names.each do |name|
|
30
24
|
association = association(name)
|
31
25
|
invalid_block = if association.reflection.klass.method_defined?(:invalid_ansestry?)
|
32
|
-
|
26
|
+
->(object) { object.invalid_ansestry? }
|
33
27
|
else
|
34
|
-
|
28
|
+
->(object) { object.invalid? }
|
35
29
|
end
|
36
30
|
|
37
31
|
ActiveData::Model::Validations::NestedValidator
|
38
32
|
.validate_nested(self, name, association.target, &invalid_block)
|
39
33
|
end
|
40
34
|
end
|
41
|
-
|
42
|
-
# Move represent attribute errors to the top level:
|
43
|
-
#
|
44
|
-
# {:'role.email' => ['Some error']}
|
45
|
-
#
|
46
|
-
# to:
|
47
|
-
#
|
48
|
-
# {email: ['Some error']}
|
49
|
-
#
|
50
|
-
def emerge_represented_attributes_errors!
|
51
|
-
self.class.represented_attributes.each do |attribute|
|
52
|
-
key = :"#{attribute.reference}.#{attribute.column}"
|
53
|
-
messages = errors.messages[key]
|
54
|
-
if messages.present?
|
55
|
-
errors[attribute.column].concat(messages)
|
56
|
-
errors.delete(key)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
35
|
end
|
61
36
|
end
|
62
37
|
end
|
@@ -1,17 +1,20 @@
|
|
1
1
|
require 'active_data/model/associations/collection/proxy'
|
2
2
|
require 'active_data/model/associations/collection/embedded'
|
3
|
-
require 'active_data/model/associations/collection/referenced'
|
4
3
|
|
5
4
|
require 'active_data/model/associations/reflections/base'
|
5
|
+
require 'active_data/model/associations/reflections/singular'
|
6
|
+
require 'active_data/model/associations/reflections/embeds_any'
|
6
7
|
require 'active_data/model/associations/reflections/embeds_one'
|
7
8
|
require 'active_data/model/associations/reflections/embeds_many'
|
8
|
-
require 'active_data/model/associations/reflections/
|
9
|
+
require 'active_data/model/associations/reflections/references_any'
|
9
10
|
require 'active_data/model/associations/reflections/references_one'
|
10
11
|
require 'active_data/model/associations/reflections/references_many'
|
11
12
|
|
12
13
|
require 'active_data/model/associations/base'
|
14
|
+
require 'active_data/model/associations/embeds_any'
|
13
15
|
require 'active_data/model/associations/embeds_one'
|
14
16
|
require 'active_data/model/associations/embeds_many'
|
17
|
+
require 'active_data/model/associations/references_any'
|
15
18
|
require 'active_data/model/associations/references_one'
|
16
19
|
require 'active_data/model/associations/references_many'
|
17
20
|
|
@@ -25,7 +28,6 @@ module ActiveData
|
|
25
28
|
|
26
29
|
included do
|
27
30
|
include NestedAttributes
|
28
|
-
include Validations
|
29
31
|
|
30
32
|
class_attribute :_associations, :_association_aliases, instance_reader: false, instance_writer: false
|
31
33
|
self._associations = {}
|
@@ -54,13 +56,13 @@ module ActiveData
|
|
54
56
|
|
55
57
|
def alias_association(alias_name, association_name)
|
56
58
|
reflection = reflect_on_association(association_name)
|
57
|
-
raise ArgumentError
|
59
|
+
raise ArgumentError, "Can't alias undefined association `#{attribute_name}` on #{self}" unless reflection
|
58
60
|
reflection.class.generate_methods alias_name, generated_associations_methods
|
59
61
|
self._association_aliases = _association_aliases.merge(alias_name.to_sym => reflection.name)
|
60
62
|
reflection
|
61
63
|
end
|
62
64
|
|
63
|
-
def reflect_on_association
|
65
|
+
def reflect_on_association(name)
|
64
66
|
name = name.to_sym
|
65
67
|
_associations[_association_aliases[name] || name]
|
66
68
|
end
|
@@ -83,17 +85,17 @@ module ActiveData
|
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
86
|
-
def ==
|
88
|
+
def ==(other)
|
87
89
|
super && association_names.all? do |association|
|
88
90
|
public_send(association) == other.public_send(association)
|
89
91
|
end
|
90
92
|
end
|
91
93
|
alias_method :eql?, :==
|
92
94
|
|
93
|
-
def association
|
94
|
-
|
95
|
-
|
96
|
-
|
95
|
+
def association(name)
|
96
|
+
reflection = self.class.reflect_on_association(name)
|
97
|
+
return unless reflection
|
98
|
+
(@_associations ||= {})[reflection.name] ||= reflection.build_association(self)
|
97
99
|
end
|
98
100
|
|
99
101
|
def apply_association_changes!
|
@@ -4,7 +4,7 @@ module ActiveData
|
|
4
4
|
class Attribute < Base
|
5
5
|
delegate :defaultizer, :enumerizer, :normalizers, to: :reflection
|
6
6
|
|
7
|
-
def write
|
7
|
+
def write(value)
|
8
8
|
return if readonly?
|
9
9
|
pollute do
|
10
10
|
write_value value
|
@@ -27,8 +27,8 @@ module ActiveData
|
|
27
27
|
defaultizer.is_a?(Proc) ? evaluate(&defaultizer) : defaultizer
|
28
28
|
end
|
29
29
|
|
30
|
-
def defaultize
|
31
|
-
defaultizer && value.nil? ? default_value || default : value
|
30
|
+
def defaultize(value, default_value = nil)
|
31
|
+
!defaultizer.nil? && value.nil? ? default_value || default : value
|
32
32
|
end
|
33
33
|
|
34
34
|
def enum
|
@@ -44,25 +44,25 @@ module ActiveData
|
|
44
44
|
end.to_set
|
45
45
|
end
|
46
46
|
|
47
|
-
def enumerize
|
47
|
+
def enumerize(value)
|
48
48
|
set = enum if enumerizer
|
49
49
|
value if !set || (set.none? || set.include?(value))
|
50
50
|
end
|
51
51
|
|
52
|
-
def normalize
|
52
|
+
def normalize(value)
|
53
53
|
if normalizers.none?
|
54
54
|
value
|
55
55
|
else
|
56
|
-
normalizers.inject(value) do |
|
56
|
+
normalizers.inject(value) do |val, normalizer|
|
57
57
|
case normalizer
|
58
58
|
when Proc
|
59
|
-
evaluate(
|
59
|
+
evaluate(val, &normalizer)
|
60
60
|
when Hash
|
61
|
-
normalizer.inject(
|
62
|
-
ActiveData.normalizer(name).call(
|
61
|
+
normalizer.inject(val) do |v, (name, options)|
|
62
|
+
ActiveData.normalizer(name).call(v, options, self)
|
63
63
|
end
|
64
64
|
else
|
65
|
-
ActiveData.normalizer(normalizer).call(
|
65
|
+
ActiveData.normalizer(normalizer).call(val, {}, self)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
@@ -5,20 +5,21 @@ module ActiveData
|
|
5
5
|
attr_reader :name, :owner
|
6
6
|
delegate :type, :typecaster, :readonly, to: :reflection
|
7
7
|
|
8
|
-
def initialize
|
9
|
-
@name
|
8
|
+
def initialize(name, owner)
|
9
|
+
@name = name
|
10
|
+
@owner = owner
|
10
11
|
end
|
11
12
|
|
12
13
|
def reflection
|
13
14
|
@owner.class._attributes[name]
|
14
15
|
end
|
15
16
|
|
16
|
-
def write_value
|
17
|
+
def write_value(value)
|
17
18
|
reset
|
18
19
|
@value_cache = value
|
19
20
|
end
|
20
21
|
|
21
|
-
def write
|
22
|
+
def write(value)
|
22
23
|
return if readonly?
|
23
24
|
write_value value
|
24
25
|
end
|
@@ -43,7 +44,7 @@ module ActiveData
|
|
43
44
|
!(read.respond_to?(:zero?) ? read.zero? : read.blank?)
|
44
45
|
end
|
45
46
|
|
46
|
-
def typecast
|
47
|
+
def typecast(value)
|
47
48
|
if value.instance_of?(type)
|
48
49
|
value
|
49
50
|
else
|
@@ -86,12 +87,12 @@ module ActiveData
|
|
86
87
|
|
87
88
|
private
|
88
89
|
|
89
|
-
def evaluate
|
90
|
+
def evaluate(*args, &block)
|
90
91
|
if block.arity >= 0 && block.arity <= args.length
|
91
92
|
owner.instance_exec(*args.first(block.arity), &block)
|
92
93
|
else
|
93
94
|
args = block.arity < 0 ? args : args.first(block.arity)
|
94
|
-
|
95
|
+
yield(*args, owner)
|
95
96
|
end
|
96
97
|
end
|
97
98
|
|
@@ -14,25 +14,25 @@ module ActiveData
|
|
14
14
|
end]
|
15
15
|
end
|
16
16
|
|
17
|
-
def write_locale
|
17
|
+
def write_locale(value, locale)
|
18
18
|
pollute do
|
19
19
|
write(read.merge(locale.to_s => value))
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def read_locale
|
23
|
+
def read_locale(locale)
|
24
24
|
read[owner.class.fallbacks(locale).detect do |fallback|
|
25
25
|
read[fallback.to_s]
|
26
26
|
end.to_s]
|
27
27
|
end
|
28
28
|
|
29
|
-
def read_locale_before_type_cast
|
29
|
+
def read_locale_before_type_cast(locale)
|
30
30
|
read_before_type_cast[owner.class.fallbacks(locale).detect do |fallback|
|
31
31
|
read_before_type_cast[fallback.to_s]
|
32
32
|
end.to_s]
|
33
33
|
end
|
34
34
|
|
35
|
-
def locale_query
|
35
|
+
def locale_query(locale)
|
36
36
|
value = read_locale(locale)
|
37
37
|
!(value.respond_to?(:zero?) ? value.zero? : value.blank?)
|
38
38
|
end
|
@@ -2,19 +2,17 @@ module ActiveData
|
|
2
2
|
module Model
|
3
3
|
module Attributes
|
4
4
|
class ReferenceMany < ReferenceOne
|
5
|
-
def read_before_type_cast
|
6
|
-
variable_cache(:value_before_type_cast) do
|
7
|
-
Array.wrap(@value_cache)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
5
|
def type_casted_value
|
14
6
|
variable_cache(:value) do
|
15
7
|
read_before_type_cast.map { |id| typecast(id) }
|
16
8
|
end
|
17
9
|
end
|
10
|
+
|
11
|
+
def read_before_type_cast
|
12
|
+
variable_cache(:value_before_type_cast) do
|
13
|
+
Array.wrap(@value_cache)
|
14
|
+
end
|
15
|
+
end
|
18
16
|
end
|
19
17
|
end
|
20
18
|
end
|