ar_doc_store 0.0.5 → 0.0.6
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/lib/ar_doc_store.rb +19 -3
- data/lib/ar_doc_store/attribute_types/base.rb +1 -0
- data/lib/ar_doc_store/attribute_types/boolean.rb +1 -3
- data/lib/ar_doc_store/attribute_types/embeds_many.rb +102 -0
- data/lib/ar_doc_store/{embedding → attribute_types}/embeds_one.rb +22 -35
- data/lib/ar_doc_store/attribute_types/uuid.rb +37 -0
- data/lib/ar_doc_store/embeddable_model.rb +20 -14
- data/lib/ar_doc_store/embedding.rb +45 -2
- data/lib/ar_doc_store/storage.rb +8 -3
- data/lib/ar_doc_store/version.rb +1 -1
- data/test/embedding_test.rb +26 -1
- metadata +5 -5
- data/lib/ar_doc_store/embedding/core.rb +0 -30
- data/lib/ar_doc_store/embedding/embeds_many.rb +0 -95
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 768bd78def2275242d66654ea62177ded6df21eb
|
4
|
+
data.tar.gz: 62c9f288637be16cfbf353b57acbfed050dbbcb8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c41aea7206dfc929c14c6d6a09e3c7132007f51245b5a754a77c2c352622fd9609b235d1048addaaa41f3ee5b2b2131e1776cb845518032cf0320c6fcca59b5
|
7
|
+
data.tar.gz: f1e58cbec99ea28a87fdcea51242fa5a69d84b01754b5fce69c46ec0244463eb3dc708802b0c533d04fbb4c0c0e00206d47732e1f4996abfbf7d3ce4642335d6
|
data/lib/ar_doc_store.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
require "ar_doc_store/version"
|
2
2
|
require "ar_doc_store/storage"
|
3
|
-
require "ar_doc_store/embedding/embeds_one"
|
4
|
-
require "ar_doc_store/embedding/embeds_many"
|
5
|
-
require "ar_doc_store/embedding/core"
|
6
3
|
require "ar_doc_store/embedding"
|
7
4
|
require "ar_doc_store/model"
|
8
5
|
require "ar_doc_store/embeddable_model"
|
@@ -13,6 +10,9 @@ require "ar_doc_store/attribute_types/enumeration"
|
|
13
10
|
require "ar_doc_store/attribute_types/float"
|
14
11
|
require "ar_doc_store/attribute_types/integer"
|
15
12
|
require "ar_doc_store/attribute_types/string"
|
13
|
+
require "ar_doc_store/attribute_types/uuid"
|
14
|
+
require "ar_doc_store/attribute_types/embeds_one"
|
15
|
+
require "ar_doc_store/attribute_types/embeds_many"
|
16
16
|
|
17
17
|
module ArDocStore
|
18
18
|
@mappings = Hash.new
|
@@ -26,4 +26,20 @@ module ArDocStore
|
|
26
26
|
def self.mappings
|
27
27
|
@mappings
|
28
28
|
end
|
29
|
+
|
30
|
+
def self.convert_boolean(bool)
|
31
|
+
if bool.is_a?(String)
|
32
|
+
return true if bool == true || bool =~ (/^(true|t|yes|y|1)$/i)
|
33
|
+
return false if bool == false || bool.blank? || bool =~ (/^(false|f|no|n|0)$/i)
|
34
|
+
elsif bool.is_a?(Integer)
|
35
|
+
return bool > 0
|
36
|
+
elsif bool.is_a?(TrueClass)
|
37
|
+
return true
|
38
|
+
elsif bool.is_a?(FalseClass)
|
39
|
+
return false
|
40
|
+
else
|
41
|
+
return nil
|
42
|
+
end
|
43
|
+
end
|
29
44
|
end
|
45
|
+
|
@@ -8,9 +8,7 @@ module ArDocStore
|
|
8
8
|
store_accessor :data, key
|
9
9
|
define_method "#{key}?".to_sym, -> { !!key }
|
10
10
|
define_method "#{key}=".to_sym, -> (value) {
|
11
|
-
res =
|
12
|
-
res = true if value == 'true' || value == true || value == '1' || value == 1
|
13
|
-
res = false if value == 'false' || value == false || value == '0' || value == 0
|
11
|
+
res = ArDocStore.convert_boolean(value)
|
14
12
|
write_store_attribute(:data, key, res)
|
15
13
|
}
|
16
14
|
add_ransacker(key, 'bool')
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module AttributeTypes
|
3
|
+
|
4
|
+
class EmbedsManyAttribute < Base
|
5
|
+
def build
|
6
|
+
assn_name = attribute.to_sym
|
7
|
+
class_name = options[:class_name] || attribute.to_s.classify
|
8
|
+
model.store_accessor :data, assn_name
|
9
|
+
create_embeds_many_accessors(assn_name, class_name)
|
10
|
+
create_embeds_many_attributes_method(assn_name)
|
11
|
+
create_embeds_many_validation(assn_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def create_embeds_many_accessors(assn_name, class_name)
|
17
|
+
model.class_eval do
|
18
|
+
define_method assn_name.to_sym, -> {
|
19
|
+
ivar = "@#{assn_name}"
|
20
|
+
existing = instance_variable_get(ivar)
|
21
|
+
return existing if existing
|
22
|
+
my_class_name = class_name.constantize
|
23
|
+
items = read_store_attribute(:data, assn_name)
|
24
|
+
if items.present? && items.first.respond_to?(:keys)
|
25
|
+
items = items.map { |item| my_class_name.new(item) }
|
26
|
+
end
|
27
|
+
items ||= []
|
28
|
+
instance_variable_set ivar, (items)
|
29
|
+
items
|
30
|
+
}
|
31
|
+
define_method "#{assn_name}=".to_sym, -> (values) {
|
32
|
+
if values && values.respond_to?(:map)
|
33
|
+
items = values.map { |item|
|
34
|
+
my_class_name = class_name.constantize
|
35
|
+
item.is_a?(my_class_name) ? item : my_class_name.new(item)
|
36
|
+
}
|
37
|
+
else
|
38
|
+
items = []
|
39
|
+
end
|
40
|
+
instance_variable_set "@#{assn_name}", write_store_attribute(:data, assn_name, items)
|
41
|
+
# data_will_change!
|
42
|
+
}
|
43
|
+
define_method "build_#{assn_name.to_s.singularize}", -> (attributes=nil) {
|
44
|
+
assns = self.public_send assn_name
|
45
|
+
item = class_name.constantize.new attributes
|
46
|
+
assns << item
|
47
|
+
public_send "#{assn_name}=", assns
|
48
|
+
item
|
49
|
+
}
|
50
|
+
|
51
|
+
define_method "ensure_#{assn_name.to_s.singularize}", -> {
|
52
|
+
public_send "build_#{assn_name.to_s.singularize}" if self.public_send(assn_name).blank?
|
53
|
+
}
|
54
|
+
# TODO: alias here instead of show the same code twice?
|
55
|
+
define_method "ensure_#{assn_name}", -> {
|
56
|
+
public_send "build_#{assn_name.to_s.singularize}" if self.public_send(assn_name).blank?
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_embeds_many_attributes_method(assn_name)
|
62
|
+
model.class_eval do
|
63
|
+
define_method "#{assn_name}_attributes=", -> (values) {
|
64
|
+
values = values && values.values || []
|
65
|
+
models = public_send assn_name
|
66
|
+
new_models = []
|
67
|
+
values.each { |value|
|
68
|
+
value.symbolize_keys!
|
69
|
+
if value.key?(:id)
|
70
|
+
next if value.key?(:_destroy) && ArDocStore.convert_boolean(value[:_destroy])
|
71
|
+
existing = models.detect { |item| item.id == value[:id] }
|
72
|
+
if existing
|
73
|
+
new_models << existing.apply_attributes(value)
|
74
|
+
else
|
75
|
+
# If there was an ID but we can't find it now, do we add it back or ignore it?
|
76
|
+
# Right now, add it back.
|
77
|
+
new_models << public_send("build_#{assn_name}", value)
|
78
|
+
end
|
79
|
+
else
|
80
|
+
new_models << public_send("build_#{assn_name}", value)
|
81
|
+
end
|
82
|
+
}
|
83
|
+
public_send "#{assn_name}=", new_models
|
84
|
+
# values = values.reject { |item| item[:_destroy] && item[:_destroy].to_bool }
|
85
|
+
# public_send "#{assn_name}=", values
|
86
|
+
}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_embeds_many_validation(assn_name)
|
91
|
+
model.class_eval do
|
92
|
+
validate_method = "validate_embedded_record_for_#{assn_name}"
|
93
|
+
define_method validate_method, -> { validate_embeds_many assn_name }
|
94
|
+
validate validate_method
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
@@ -1,36 +1,19 @@
|
|
1
1
|
module ArDocStore
|
2
|
-
module
|
3
|
-
module EmbedsOne
|
4
|
-
|
5
|
-
def self.included(base)
|
6
|
-
base.send :extend, ClassMethods
|
7
|
-
base.send :include, InstanceMethods
|
8
|
-
end
|
9
|
-
|
10
|
-
module InstanceMethods
|
11
|
-
|
12
|
-
def validate_embeds_one(assn_name)
|
13
|
-
record = public_send(assn_name)
|
14
|
-
embed_valid?(assn_name, record) if record
|
15
|
-
end
|
2
|
+
module AttributeTypes
|
16
3
|
|
4
|
+
class EmbedsOneAttribute < Base
|
5
|
+
def build
|
6
|
+
assn_name = attribute.to_sym
|
7
|
+
class_name = options[:class_name] || attribute.to_s.classify
|
8
|
+
model.store_accessor :data, assn_name
|
9
|
+
model.store_attribute_from_class class_name, assn_name
|
10
|
+
create_embed_one_attributes_method(assn_name)
|
11
|
+
create_embeds_one_accessors assn_name, class_name
|
12
|
+
create_embeds_one_validation(assn_name)
|
17
13
|
end
|
18
|
-
|
19
|
-
module ClassMethods
|
20
|
-
|
21
|
-
def embeds_one(assn_name, *args)
|
22
|
-
store_accessor :data, assn_name
|
23
|
-
options = args.extract_options!
|
24
|
-
class_name = options[:class_name] || assn_name.to_s.classify
|
25
|
-
store_attribute_from_class class_name, assn_name
|
26
|
-
create_embed_one_attributes_method(assn_name)
|
27
|
-
create_embeds_one_accessors assn_name, class_name
|
28
|
-
create_embeds_one_validation(assn_name)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
14
|
|
33
|
-
|
15
|
+
def create_embeds_one_accessors(assn_name, class_name)
|
16
|
+
model.class_eval do
|
34
17
|
define_method "build_#{assn_name}", -> (attributes=nil) {
|
35
18
|
class_name = class_name.constantize if class_name.respond_to?(:constantize)
|
36
19
|
public_send "#{assn_name}=", class_name.new(attributes)
|
@@ -40,10 +23,11 @@ module ArDocStore
|
|
40
23
|
public_send "build_#{assn_name}" if public_send(assn_name).blank?
|
41
24
|
}
|
42
25
|
end
|
26
|
+
end
|
43
27
|
|
44
|
-
|
28
|
+
def create_embed_one_attributes_method(assn_name)
|
29
|
+
model.class_eval do
|
45
30
|
define_method "#{assn_name}_attributes=", -> (values) {
|
46
|
-
# data_will_change!
|
47
31
|
values ||= {}
|
48
32
|
values.symbolize_keys! if values.respond_to?(:symbolize_keys!)
|
49
33
|
if values[:_destroy] && (values[:_destroy] == '1')
|
@@ -53,15 +37,18 @@ module ArDocStore
|
|
53
37
|
end
|
54
38
|
}
|
55
39
|
end
|
40
|
+
end
|
56
41
|
|
57
|
-
|
42
|
+
def create_embeds_one_validation(assn_name)
|
43
|
+
model.class_eval do
|
58
44
|
validate_method = "validate_embedded_record_for_#{assn_name}"
|
59
45
|
define_method validate_method, -> { validate_embeds_one assn_name }
|
60
46
|
validate validate_method
|
61
|
-
end
|
62
|
-
|
47
|
+
end
|
63
48
|
end
|
64
|
-
|
49
|
+
|
50
|
+
|
65
51
|
end
|
52
|
+
|
66
53
|
end
|
67
54
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module ArDocStore
|
4
|
+
module AttributeTypes
|
5
|
+
|
6
|
+
class UuidAttribute < Base
|
7
|
+
def build
|
8
|
+
key = attribute.to_sym
|
9
|
+
model.class_eval do
|
10
|
+
store_accessor :data, key
|
11
|
+
define_method "#{key}?".to_sym, -> { !!key }
|
12
|
+
define_method key, -> {
|
13
|
+
value = read_store_attribute(:data, key)
|
14
|
+
unless value
|
15
|
+
value = SecureRandom.uuid
|
16
|
+
write_store_attribute :data, key, value
|
17
|
+
end
|
18
|
+
value
|
19
|
+
}
|
20
|
+
define_method "#{key}=".to_sym, -> (value) {
|
21
|
+
res = nil
|
22
|
+
res = true if value == 'true' || value == true || value == '1' || value == 1
|
23
|
+
res = false if value == 'false' || value == false || value == '0' || value == 0
|
24
|
+
write_store_attribute(:data, key, res)
|
25
|
+
}
|
26
|
+
add_ransacker(key, 'text')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def type
|
31
|
+
:boolean
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -4,17 +4,6 @@ module ArDocStore
|
|
4
4
|
|
5
5
|
def self.included(mod)
|
6
6
|
|
7
|
-
mod.class_eval do
|
8
|
-
attr_accessor :_destroy
|
9
|
-
attr_accessor :attributes
|
10
|
-
|
11
|
-
class_attribute :virtual_attributes
|
12
|
-
self.virtual_attributes ||= HashWithIndifferentAccess.new
|
13
|
-
|
14
|
-
delegate :as_json, to: :attributes
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
7
|
mod.send :include, ArDocStore::Storage
|
19
8
|
mod.send :include, ArDocStore::Embedding
|
20
9
|
mod.send :include, InstanceMethods
|
@@ -26,13 +15,29 @@ module ArDocStore
|
|
26
15
|
mod.send :include, ActiveModel::Dirty
|
27
16
|
mod.send :include, ActiveModel::Serialization
|
28
17
|
|
18
|
+
mod.class_eval do
|
19
|
+
attr_accessor :_destroy
|
20
|
+
attr_accessor :attributes
|
21
|
+
|
22
|
+
class_attribute :virtual_attributes
|
23
|
+
self.virtual_attributes ||= HashWithIndifferentAccess.new
|
24
|
+
|
25
|
+
delegate :as_json, to: :attributes
|
26
|
+
|
27
|
+
attribute :id, :uuid
|
28
|
+
end
|
29
|
+
|
29
30
|
end
|
30
31
|
|
31
32
|
module InstanceMethods
|
32
33
|
|
33
|
-
def initialize(attrs=
|
34
|
-
attrs ||= {}
|
34
|
+
def initialize(attrs=HashWithIndifferentAccess.new)
|
35
35
|
@attributes = HashWithIndifferentAccess.new
|
36
|
+
apply_attributes attrs
|
37
|
+
end
|
38
|
+
|
39
|
+
def apply_attributes(attrs=HashWithIndifferentAccess.new)
|
40
|
+
return self unless attrs
|
36
41
|
attrs.each { |key, value|
|
37
42
|
key = "#{key}=".to_sym
|
38
43
|
self.public_send(key, value) if methods.include?(key)
|
@@ -40,6 +45,7 @@ module ArDocStore
|
|
40
45
|
virtual_attributes.keys.each do |attr|
|
41
46
|
@attributes[attr] ||= nil
|
42
47
|
end
|
48
|
+
self
|
43
49
|
end
|
44
50
|
|
45
51
|
def persisted?
|
@@ -69,7 +75,7 @@ module ArDocStore
|
|
69
75
|
|
70
76
|
def store_accessor(store, key)
|
71
77
|
self.virtual_attributes ||= HashWithIndifferentAccess.new
|
72
|
-
virtual_attributes[key]
|
78
|
+
virtual_attributes[key] ||= true
|
73
79
|
key = key.to_sym
|
74
80
|
define_method key, -> { read_store_attribute(:data, key) }
|
75
81
|
define_method "#{key}=".to_sym, -> (value) { write_store_attribute :data, key, value }
|
@@ -1,7 +1,50 @@
|
|
1
1
|
module ArDocStore
|
2
2
|
module Embedding
|
3
|
-
def self.included(
|
4
|
-
|
3
|
+
def self.included(mod)
|
4
|
+
mod.send :extend, ClassMethods
|
5
|
+
mod.send :include, InstanceMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def embeds_many(assn_name, *args)
|
11
|
+
attribute assn_name, :embeds_many, *args
|
12
|
+
end
|
13
|
+
|
14
|
+
def embeds_one(assn_name, *args)
|
15
|
+
attribute assn_name, :embeds_one, *args
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
module InstanceMethods
|
22
|
+
|
23
|
+
# Returns whether or not the association is valid and applies any errors to
|
24
|
+
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
|
25
|
+
# enabled records if they're marked_for_destruction? or destroyed.
|
26
|
+
def embed_valid?(assn_name, record)
|
27
|
+
unless valid = record.valid?
|
28
|
+
record.errors.each do |attribute, message|
|
29
|
+
attribute = "#{assn_name}.#{attribute}"
|
30
|
+
errors[attribute] << message
|
31
|
+
errors[attribute].uniq!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
valid
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_embeds_many(assn_name)
|
38
|
+
if records = public_send(assn_name)
|
39
|
+
records.each { |record| embed_valid?(assn_name, record) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate_embeds_one(assn_name)
|
44
|
+
record = public_send(assn_name)
|
45
|
+
embed_valid?(assn_name, record) if record
|
46
|
+
end
|
47
|
+
|
5
48
|
end
|
6
49
|
end
|
7
50
|
end
|
data/lib/ar_doc_store/storage.rb
CHANGED
@@ -2,6 +2,10 @@ module ArDocStore
|
|
2
2
|
module Storage
|
3
3
|
|
4
4
|
def self.included(mod)
|
5
|
+
|
6
|
+
mod.class_attribute :virtual_attributes
|
7
|
+
mod.virtual_attributes ||= HashWithIndifferentAccess.new
|
8
|
+
|
5
9
|
mod.send :include, InstanceMethods
|
6
10
|
mod.send :extend, ClassMethods
|
7
11
|
end
|
@@ -105,11 +109,12 @@ module ArDocStore
|
|
105
109
|
}
|
106
110
|
define_method "#{key}=".to_sym, -> (value) {
|
107
111
|
ivar = "@#{key}"
|
112
|
+
existing = public_send(key)
|
108
113
|
class_name = class_name.constantize if class_name.respond_to?(:constantize)
|
109
|
-
if value == ''
|
114
|
+
if value == '' || !value
|
110
115
|
value = nil
|
111
|
-
|
112
|
-
value =
|
116
|
+
elsif !value.is_a?(class_name)
|
117
|
+
value = existing.apply_attributes(value)
|
113
118
|
end
|
114
119
|
instance_variable_set ivar, value
|
115
120
|
write_store_attribute :data, key, value
|
data/lib/ar_doc_store/version.rb
CHANGED
data/test/embedding_test.rb
CHANGED
@@ -23,6 +23,31 @@ class EmbeddingTest < MiniTest::Test
|
|
23
23
|
assert_nil restroom.door.clear_distance
|
24
24
|
end
|
25
25
|
|
26
|
+
def test_attributes_equals_sets_partial_attributes
|
27
|
+
restroom = Restroom.new door_attributes: { clear_distance: 5, opening_force: 13, clear_space: 43 }
|
28
|
+
restroom.door_attributes = { clear_distance: 7 }
|
29
|
+
assert_equal 7, restroom.door.clear_distance
|
30
|
+
assert_equal 13, restroom.door.opening_force
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_embeds_many_attributes_equals_sets_partial_attributes
|
34
|
+
building = Building.new
|
35
|
+
building.restrooms << Restroom.new(door_attributes: { clear_distance: 5, opening_force: 13, clear_space: 43 })
|
36
|
+
building.restrooms << Restroom.new(door_attributes: { clear_distance: 6, opening_force: 14, clear_space: 44 })
|
37
|
+
building.restrooms << Restroom.new(door_attributes: { clear_distance: 7, opening_force: 15, clear_space: 45 })
|
38
|
+
restrooms_attributes = {
|
39
|
+
a1: { id: building.restrooms[0].id, door_attributes: { clear_distance: 10 } },
|
40
|
+
a2: { id: building.restrooms[1].id, _destroy: true },
|
41
|
+
a3: { id: building.restrooms[2].id, door_attributes: { clear_distance: 1 } }
|
42
|
+
}
|
43
|
+
building.restrooms_attributes = restrooms_attributes
|
44
|
+
assert_equal 2, building.restrooms.size
|
45
|
+
assert_equal 10, building.restrooms.first.door.clear_distance
|
46
|
+
assert_equal 15, building.restrooms.last.door.opening_force
|
47
|
+
assert_equal 1, building.restrooms.last.door.clear_distance
|
48
|
+
assert_nil building.restrooms.detect {|restroom| restroom.id == restrooms_attributes[:a2][:id] }
|
49
|
+
end
|
50
|
+
|
26
51
|
def test_attribute_validity_of_embedded_model_from_model
|
27
52
|
b = Building.new
|
28
53
|
r = Restroom.new
|
@@ -37,7 +62,7 @@ class EmbeddingTest < MiniTest::Test
|
|
37
62
|
end
|
38
63
|
|
39
64
|
def test_model_subclassing
|
40
|
-
assert_equal EmbeddableB.virtual_attributes.size,
|
65
|
+
assert_equal EmbeddableB.virtual_attributes.size, 3
|
41
66
|
end
|
42
67
|
|
43
68
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar_doc_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Furber
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -72,15 +72,15 @@ files:
|
|
72
72
|
- lib/ar_doc_store/attribute_types/array.rb
|
73
73
|
- lib/ar_doc_store/attribute_types/base.rb
|
74
74
|
- lib/ar_doc_store/attribute_types/boolean.rb
|
75
|
+
- lib/ar_doc_store/attribute_types/embeds_many.rb
|
76
|
+
- lib/ar_doc_store/attribute_types/embeds_one.rb
|
75
77
|
- lib/ar_doc_store/attribute_types/enumeration.rb
|
76
78
|
- lib/ar_doc_store/attribute_types/float.rb
|
77
79
|
- lib/ar_doc_store/attribute_types/integer.rb
|
78
80
|
- lib/ar_doc_store/attribute_types/string.rb
|
81
|
+
- lib/ar_doc_store/attribute_types/uuid.rb
|
79
82
|
- lib/ar_doc_store/embeddable_model.rb
|
80
83
|
- lib/ar_doc_store/embedding.rb
|
81
|
-
- lib/ar_doc_store/embedding/core.rb
|
82
|
-
- lib/ar_doc_store/embedding/embeds_many.rb
|
83
|
-
- lib/ar_doc_store/embedding/embeds_one.rb
|
84
84
|
- lib/ar_doc_store/model.rb
|
85
85
|
- lib/ar_doc_store/storage.rb
|
86
86
|
- lib/ar_doc_store/version.rb
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module ArDocStore
|
2
|
-
module Embedding
|
3
|
-
module Core
|
4
|
-
|
5
|
-
def self.included(mod)
|
6
|
-
mod.send :include, EmbedsOne
|
7
|
-
mod.send :include, EmbedsMany
|
8
|
-
mod.send :include, InstanceMethods
|
9
|
-
end
|
10
|
-
|
11
|
-
module InstanceMethods
|
12
|
-
|
13
|
-
# Returns whether or not the association is valid and applies any errors to
|
14
|
-
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
|
15
|
-
# enabled records if they're marked_for_destruction? or destroyed.
|
16
|
-
def embed_valid?(assn_name, record)
|
17
|
-
unless valid = record.valid?
|
18
|
-
record.errors.each do |attribute, message|
|
19
|
-
attribute = "#{assn_name}.#{attribute}"
|
20
|
-
errors[attribute] << message
|
21
|
-
errors[attribute].uniq!
|
22
|
-
end
|
23
|
-
end
|
24
|
-
valid
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,95 +0,0 @@
|
|
1
|
-
module ArDocStore
|
2
|
-
module Embedding
|
3
|
-
module EmbedsMany
|
4
|
-
|
5
|
-
def self.included(base)
|
6
|
-
base.send :extend, ClassMethods
|
7
|
-
base.send :include, InstanceMethods
|
8
|
-
end
|
9
|
-
|
10
|
-
module InstanceMethods
|
11
|
-
# Validate the embedded records
|
12
|
-
def validate_embeds_many(assn_name)
|
13
|
-
if records = public_send(assn_name)
|
14
|
-
records.each { |record| embed_valid?(assn_name, record) }
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
module ClassMethods
|
21
|
-
|
22
|
-
def embeds_many(assn_name, *args)
|
23
|
-
store_accessor :data, assn_name
|
24
|
-
options = args.extract_options!
|
25
|
-
class_name = options[:class_name] || assn_name.to_s.classify
|
26
|
-
create_embeds_many_accessors(assn_name, class_name)
|
27
|
-
create_embed_many_attributes_method(assn_name)
|
28
|
-
create_embeds_many_validation(assn_name)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def create_embeds_many_accessors(assn_name, class_name)
|
34
|
-
define_method assn_name.to_sym, -> {
|
35
|
-
ivar = "@#{assn_name}"
|
36
|
-
existing = instance_variable_get(ivar)
|
37
|
-
return existing if existing
|
38
|
-
my_class_name = class_name.constantize
|
39
|
-
items = read_store_attribute(:data, assn_name)
|
40
|
-
if items.present? && items.first.respond_to?(:keys)
|
41
|
-
items = items.map { |item| my_class_name.new(item) }
|
42
|
-
end
|
43
|
-
items ||= []
|
44
|
-
instance_variable_set ivar, (items)
|
45
|
-
items
|
46
|
-
}
|
47
|
-
define_method "#{assn_name}=".to_sym, -> (values) {
|
48
|
-
if values && values.respond_to?(:map)
|
49
|
-
items = values.map { |item|
|
50
|
-
my_class_name = class_name.constantize
|
51
|
-
item.is_a?(my_class_name) ? item : my_class_name.new(item)
|
52
|
-
}
|
53
|
-
else
|
54
|
-
items = []
|
55
|
-
end
|
56
|
-
instance_variable_set "@#{assn_name}", write_store_attribute(:data, assn_name, items)
|
57
|
-
# data_will_change!
|
58
|
-
}
|
59
|
-
define_method "build_#{assn_name.to_s.singularize}", -> (attributes=nil) {
|
60
|
-
assns = self.public_send assn_name
|
61
|
-
item = class_name.constantize.new attributes
|
62
|
-
assns << item
|
63
|
-
public_send "#{assn_name}=", assns
|
64
|
-
item
|
65
|
-
}
|
66
|
-
|
67
|
-
define_method "ensure_#{assn_name.to_s.singularize}", -> {
|
68
|
-
public_send "build_#{assn_name.to_s.singularize}" if self.public_send(assn_name).blank?
|
69
|
-
}
|
70
|
-
# TODO: alias here instead of show the same code twice?
|
71
|
-
define_method "ensure_#{assn_name}", -> {
|
72
|
-
public_send "build_#{assn_name.to_s.singularize}" if self.public_send(assn_name).blank?
|
73
|
-
}
|
74
|
-
end
|
75
|
-
|
76
|
-
def create_embed_many_attributes_method(assn_name)
|
77
|
-
define_method "#{assn_name}_attributes=", -> (values) {
|
78
|
-
data_will_change!
|
79
|
-
values = values.andand.values || []
|
80
|
-
values = values.reject { |item| item['_destroy'] == '1' }
|
81
|
-
public_send "#{assn_name}=", values
|
82
|
-
}
|
83
|
-
end
|
84
|
-
|
85
|
-
def create_embeds_many_validation(assn_name)
|
86
|
-
validate_method = "validate_embedded_record_for_#{assn_name}"
|
87
|
-
define_method validate_method, -> { validate_embeds_many assn_name }
|
88
|
-
validate validate_method
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|