ar_doc_store 1.0.5 → 2.0.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/ar_doc_store.gemspec +3 -3
- data/lib/ar_doc_store.rb +30 -28
- data/lib/ar_doc_store/attributes/array.rb +25 -0
- data/lib/ar_doc_store/attributes/base.rb +72 -0
- data/lib/ar_doc_store/attributes/boolean.rb +17 -0
- data/lib/ar_doc_store/attributes/callback_support.rb +21 -0
- data/lib/ar_doc_store/attributes/date.rb +21 -0
- data/lib/ar_doc_store/attributes/datetime.rb +21 -0
- data/lib/ar_doc_store/attributes/decimal.rb +17 -0
- data/lib/ar_doc_store/attributes/embeds_base.rb +35 -0
- data/lib/ar_doc_store/attributes/embeds_many.rb +143 -0
- data/lib/ar_doc_store/{attribute_types/embeds_one_attribute.rb → attributes/embeds_one.rb} +25 -30
- data/lib/ar_doc_store/{attribute_types/enumeration_attribute.rb → attributes/enumeration.rb} +2 -6
- data/lib/ar_doc_store/{attribute_types/float_attribute.rb → attributes/float.rb} +5 -8
- data/lib/ar_doc_store/{attribute_types/integer_attribute.rb → attributes/integer.rb} +5 -8
- data/lib/ar_doc_store/attributes/string.rb +13 -0
- data/lib/ar_doc_store/embeddable_model.rb +51 -75
- data/lib/ar_doc_store/embedded_collection.rb +14 -0
- data/lib/ar_doc_store/embedding.rb +0 -2
- data/lib/ar_doc_store/model.rb +18 -8
- data/lib/ar_doc_store/storage.rb +4 -127
- data/lib/ar_doc_store/types/embeds_many.rb +52 -0
- data/lib/ar_doc_store/types/embeds_one.rb +42 -0
- data/lib/ar_doc_store/version.rb +1 -1
- data/test/{attribute_types → attributes}/array_attribute_test.rb +5 -1
- data/test/{attribute_types → attributes}/boolean_attribute_test.rb +7 -1
- data/test/attributes/date_attribute_test.rb +52 -0
- data/test/attributes/datetime_attribute_test.rb +54 -0
- data/test/attributes/decimal_attribute_test.rb +38 -0
- data/test/attributes/embeds_many_attribute_test.rb +78 -0
- data/test/attributes/embeds_one_attribute_test.rb +80 -0
- data/test/{attribute_types → attributes}/enumeration_attribute_test.rb +5 -0
- data/test/{attribute_types → attributes}/float_attribute_test.rb +6 -1
- data/test/attributes/integer_attribute_test.rb +63 -0
- data/test/{attribute_types → attributes}/string_attribute_test.rb +6 -0
- data/test/test_helper.rb +22 -94
- metadata +57 -35
- data/lib/ar_doc_store/attribute_types/array_attribute.rb +0 -30
- data/lib/ar_doc_store/attribute_types/base_attribute.rb +0 -61
- data/lib/ar_doc_store/attribute_types/boolean_attribute.rb +0 -25
- data/lib/ar_doc_store/attribute_types/datetime_attribute.rb +0 -17
- data/lib/ar_doc_store/attribute_types/embeds_many_attribute.rb +0 -165
- data/lib/ar_doc_store/attribute_types/string_attribute.rb +0 -17
- data/lib/ar_doc_store/attribute_types/uuid_attribute.rb +0 -30
- data/test/attribute_types/datetime_attribute_test.rb +0 -35
- data/test/attribute_types/integer_attribute_test.rb +0 -33
- data/test/originals/dirty_attributes_test.rb +0 -35
- data/test/originals/embedded_model_attribute_test.rb +0 -23
- data/test/originals/embedding_test.rb +0 -82
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb88a2aa2aecbb6bb9fabcfb9dfb8881e93021fa41657293736aba140468ec56
|
4
|
+
data.tar.gz: 349d77c3cafb00bae525bc36e0a51b377ca43cd0ff18f10a2dc38dfd44ea1884
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bca4ade2466cbffb2575a3c3701a4128dec040a270c9008fba0d53be29b897acd51e983a4a45c03df112b96292adcdce3d06bbcd8531fe1e47302e01cfe8530
|
7
|
+
data.tar.gz: d6e4520d4f2ef389acff98ea0c873b74999c049286cce517f458ae0364af476875437650114bfd42774ffa2774ec794f90b3fce4a96f18175b2a7ad79fc92332
|
data/ar_doc_store.gemspec
CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "activerecord"
|
22
|
-
spec.add_dependency "pg"
|
23
|
-
# spec.add_dependency "hashie", ">=3.4.0"
|
21
|
+
spec.add_dependency "activerecord", ">=5.2"
|
22
|
+
spec.add_dependency "pg"
|
24
23
|
spec.add_development_dependency "bundler", "~> 1.7"
|
25
24
|
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "simplecov"
|
26
26
|
end
|
data/lib/ar_doc_store.rb
CHANGED
@@ -3,32 +3,42 @@ require "ar_doc_store/storage"
|
|
3
3
|
require "ar_doc_store/embedding"
|
4
4
|
require "ar_doc_store/model"
|
5
5
|
require "ar_doc_store/embeddable_model"
|
6
|
+
require "ar_doc_store/embedded_collection"
|
6
7
|
|
7
8
|
module ArDocStore
|
8
9
|
|
9
|
-
module
|
10
|
-
autoload :
|
11
|
-
autoload :
|
12
|
-
autoload :
|
13
|
-
autoload :
|
14
|
-
autoload :
|
15
|
-
autoload :
|
16
|
-
autoload :
|
17
|
-
autoload :
|
18
|
-
autoload :
|
19
|
-
autoload :
|
20
|
-
autoload :
|
10
|
+
module Attributes
|
11
|
+
autoload :Base, "ar_doc_store/attributes/base"
|
12
|
+
autoload :Array, "ar_doc_store/attributes/array"
|
13
|
+
autoload :Boolean, "ar_doc_store/attributes/boolean"
|
14
|
+
autoload :Enumeration, "ar_doc_store/attributes/enumeration"
|
15
|
+
autoload :Float, "ar_doc_store/attributes/float"
|
16
|
+
autoload :Integer, "ar_doc_store/attributes/integer"
|
17
|
+
autoload :String, "ar_doc_store/attributes/string"
|
18
|
+
autoload :EmbedsOne, "ar_doc_store/attributes/embeds_one"
|
19
|
+
autoload :EmbedsMany, "ar_doc_store/attributes/embeds_many"
|
20
|
+
autoload :Datetime, "ar_doc_store/attributes/datetime"
|
21
|
+
autoload :Date, "ar_doc_store/attributes/date"
|
22
|
+
autoload :Decimal, "ar_doc_store/attributes/decimal"
|
23
|
+
autoload :CallbackSupport, "ar_doc_store/attributes/callback_support"
|
24
|
+
autoload :EmbedsBase, "ar_doc_store/attributes/embeds_base"
|
25
|
+
end
|
26
|
+
|
27
|
+
module Types
|
28
|
+
autoload :EmbedsOne, "ar_doc_store/types/embeds_one"
|
29
|
+
autoload :EmbedsMany, "ar_doc_store/types/embeds_many"
|
21
30
|
end
|
22
31
|
|
23
32
|
@mappings = Hash.new
|
24
|
-
@mappings[:array] = 'ArDocStore::
|
25
|
-
@mappings[:boolean] = 'ArDocStore::
|
26
|
-
@mappings[:enumeration] = 'ArDocStore::
|
27
|
-
@mappings[:float] = 'ArDocStore::
|
28
|
-
@mappings[:integer] = 'ArDocStore::
|
29
|
-
@mappings[:string] = 'ArDocStore::
|
30
|
-
@mappings[:
|
31
|
-
@mappings[:
|
33
|
+
@mappings[:array] = 'ArDocStore::Attributes::Array'
|
34
|
+
@mappings[:boolean] = 'ArDocStore::Attributes::Boolean'
|
35
|
+
@mappings[:enumeration] = 'ArDocStore::Attributes::Enumeration'
|
36
|
+
@mappings[:float] = 'ArDocStore::Attributes::Float'
|
37
|
+
@mappings[:integer] = 'ArDocStore::Attributes::Integer'
|
38
|
+
@mappings[:string] = 'ArDocStore::Attributes::String'
|
39
|
+
@mappings[:datetime] = 'ArDocStore::Attributes::Datetime'
|
40
|
+
@mappings[:date] = 'ArDocStore::Attributes::Date'
|
41
|
+
@mappings[:decimal] = 'ArDocStore::Attributes::Decimal'
|
32
42
|
|
33
43
|
def self.mappings
|
34
44
|
@mappings
|
@@ -48,12 +58,4 @@ module ArDocStore
|
|
48
58
|
return nil
|
49
59
|
end
|
50
60
|
end
|
51
|
-
|
52
|
-
def self.clobber_attribute_method!
|
53
|
-
ArDocStore::Storage::ClassMethods.module_eval do
|
54
|
-
def attribute(*args)
|
55
|
-
json_attribute *args
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
61
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module Attributes
|
3
|
+
class Array < Base
|
4
|
+
def define_query_method
|
5
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
6
|
+
def #{attribute}?
|
7
|
+
#{attribute}.present?
|
8
|
+
end
|
9
|
+
CODE
|
10
|
+
end
|
11
|
+
|
12
|
+
def type
|
13
|
+
:array
|
14
|
+
end
|
15
|
+
|
16
|
+
def attribute_type
|
17
|
+
ActiveModel::Type::Value
|
18
|
+
end
|
19
|
+
|
20
|
+
def attribute_options
|
21
|
+
{ array: true }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module Attributes
|
3
|
+
class Base
|
4
|
+
include CallbackSupport
|
5
|
+
|
6
|
+
attr_accessor :conversion, :predicate, :options, :model, :attribute, :default
|
7
|
+
|
8
|
+
after_build :add_ransacker
|
9
|
+
after_build :define_query_method
|
10
|
+
|
11
|
+
def self.build(model, attribute, options={})
|
12
|
+
new(model, attribute, options).build
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(model, attribute, options)
|
16
|
+
@model, @attribute, @options = model, attribute, options
|
17
|
+
@default = options.delete(:default)
|
18
|
+
end
|
19
|
+
|
20
|
+
def build
|
21
|
+
run_callbacks :build do
|
22
|
+
store_attribute
|
23
|
+
end
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
#:nodoc:
|
28
|
+
def store_attribute
|
29
|
+
attribute_name = @attribute
|
30
|
+
attribute_type = self.attribute_type
|
31
|
+
options = attribute_options
|
32
|
+
options.merge!(default: default) if default.present?
|
33
|
+
model.class_eval do
|
34
|
+
attribute attribute_name, attribute_type.new, **options
|
35
|
+
define_method "#{attribute_name}=".to_sym, -> (value) {
|
36
|
+
value = nil if value == '' || value == ['']
|
37
|
+
send :attribute=, attribute_name, value
|
38
|
+
new_value = send :attribute, attribute_name
|
39
|
+
write_store_attribute(json_column, attribute_name, new_value)
|
40
|
+
new_value
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def attribute_type
|
46
|
+
ActiveModel::Type::Value
|
47
|
+
end
|
48
|
+
|
49
|
+
def attribute_options
|
50
|
+
{}
|
51
|
+
end
|
52
|
+
|
53
|
+
def embedded?
|
54
|
+
false
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_ransacker
|
58
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
59
|
+
add_ransacker :#{attribute}, "#{predicate}"
|
60
|
+
CODE
|
61
|
+
end
|
62
|
+
|
63
|
+
def define_query_method
|
64
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
65
|
+
def #{attribute}?
|
66
|
+
!!#{attribute}
|
67
|
+
end
|
68
|
+
CODE
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module Attributes
|
3
|
+
module CallbackSupport
|
4
|
+
def self.included(mod)
|
5
|
+
mod.send :include, ActiveSupport::Callbacks
|
6
|
+
mod.send :extend, ClassMethods
|
7
|
+
mod.define_callbacks :build
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def before_build(method)
|
12
|
+
set_callback :build, :before, method
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_build(method)
|
16
|
+
set_callback :build, :after, method
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module Attributes
|
3
|
+
class Date < Base
|
4
|
+
def define_query_method
|
5
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
6
|
+
def #{attribute}?
|
7
|
+
#{attribute}.present?
|
8
|
+
end
|
9
|
+
CODE
|
10
|
+
end
|
11
|
+
|
12
|
+
def type
|
13
|
+
:date
|
14
|
+
end
|
15
|
+
|
16
|
+
def attribute_type
|
17
|
+
ActiveRecord::Type::Date
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module Attributes
|
3
|
+
class Datetime < Base
|
4
|
+
def define_query_method
|
5
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
6
|
+
def #{attribute}?
|
7
|
+
#{attribute}.present?
|
8
|
+
end
|
9
|
+
CODE
|
10
|
+
end
|
11
|
+
|
12
|
+
def type
|
13
|
+
:datetime
|
14
|
+
end
|
15
|
+
|
16
|
+
def attribute_type
|
17
|
+
ActiveRecord::Type::DateTime
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module Attributes
|
3
|
+
class EmbedsBase < Base
|
4
|
+
attr_reader :class_name
|
5
|
+
before_build :handle_options
|
6
|
+
after_build :create_build_method
|
7
|
+
after_build :create_ensure_method
|
8
|
+
after_build :create_attributes_method
|
9
|
+
after_build :create_validation
|
10
|
+
|
11
|
+
def embedded?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def handle_options
|
18
|
+
@class_name = options[:class_name] || attribute.to_s.classify
|
19
|
+
@attribute = attribute.to_sym
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_build_method
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_ensure_method
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_attributes_method
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_validation
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module Attributes
|
3
|
+
class EmbedsMany < EmbedsBase
|
4
|
+
private
|
5
|
+
|
6
|
+
def store_attribute
|
7
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
8
|
+
attribute :#{attribute}, ArDocStore::Types::EmbedsMany.new("#{@class_name}")
|
9
|
+
def #{attribute}
|
10
|
+
value = send :attribute, :#{attribute}
|
11
|
+
if value && !value.is_a?(ArDocStore::EmbeddedCollection)
|
12
|
+
value = ArDocStore::EmbeddedCollection.new value
|
13
|
+
else
|
14
|
+
value ||= ArDocStore::EmbeddedCollection.new
|
15
|
+
end
|
16
|
+
value.parent = self
|
17
|
+
value.embedded_as = :#{attribute}
|
18
|
+
value.each do |item|
|
19
|
+
item.parent = value
|
20
|
+
end
|
21
|
+
value
|
22
|
+
end
|
23
|
+
def #{attribute}=(value)
|
24
|
+
value = nil if value == '' || value == ['']
|
25
|
+
send :attribute=, :#{attribute}, value
|
26
|
+
new_value = send :attribute, :#{attribute}
|
27
|
+
new_value.parent = self
|
28
|
+
new_value.embedded_as = :#{attribute}
|
29
|
+
new_value.each do |item|
|
30
|
+
item.parent = new_value
|
31
|
+
end
|
32
|
+
write_store_attribute json_column, :#{attribute}, new_value
|
33
|
+
new_value
|
34
|
+
end
|
35
|
+
CODE
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_build_method
|
39
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
40
|
+
def build_#{attribute.to_s.singularize}(attributes = {})
|
41
|
+
items = #{attribute} || ArDocStore::EmbeddedCollection.new
|
42
|
+
items.embedded_as = :#{attribute}
|
43
|
+
items.parent = self
|
44
|
+
item = #{@class_name}.new attributes
|
45
|
+
item.parent = #{attribute}
|
46
|
+
items << item
|
47
|
+
self.#{attribute} = items
|
48
|
+
item
|
49
|
+
end
|
50
|
+
CODE
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_ensure_method
|
54
|
+
attr_singular = attribute.to_s.singularize
|
55
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
56
|
+
def ensure_#{attribute}(attributes = nil)
|
57
|
+
#{attribute}.first || build_#{attr_singular}(attributes)
|
58
|
+
end
|
59
|
+
def ensure_#{attr_singular}(attributes = nil)
|
60
|
+
#{attribute}.first || build_#{attr_singular}(attributes)
|
61
|
+
end
|
62
|
+
CODE
|
63
|
+
end
|
64
|
+
|
65
|
+
def create_attributes_method
|
66
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
67
|
+
def #{attribute}_attributes=(values)
|
68
|
+
return if values.blank?
|
69
|
+
if values.respond_to?(:each)
|
70
|
+
if values.respond_to?(:values)
|
71
|
+
values = values.values
|
72
|
+
end
|
73
|
+
else
|
74
|
+
values = [values]
|
75
|
+
end
|
76
|
+
self.#{attribute} = AssignEmbedsManyAttributes.new(self, #{@class_name}, :#{attribute}, #{attribute}, values).models
|
77
|
+
end
|
78
|
+
CODE
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_validation
|
82
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
83
|
+
def validate_embedded_record_for_#{attribute}
|
84
|
+
validate_embeds_many :#{attribute}
|
85
|
+
end
|
86
|
+
validate :validate_embedded_record_for_#{attribute}
|
87
|
+
CODE
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class AssignEmbedsManyAttributes
|
92
|
+
attr_reader :models, :assn_name, :parent, :class_name
|
93
|
+
def initialize(parent, class_name, assn_name, models, values)
|
94
|
+
@parent, @class_name, @assn_name, @models, @values = parent, class_name, assn_name, models, values
|
95
|
+
@models ||= ArDocStore::EmbeddedCollection.new
|
96
|
+
values.each { |value|
|
97
|
+
value = value.symbolize_keys
|
98
|
+
if value.key?(:id)
|
99
|
+
process_existing_model(value)
|
100
|
+
else
|
101
|
+
next if value.values.all? { |value| value.nil? || value == '' }
|
102
|
+
add(value)
|
103
|
+
end
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
attr_writer :models, :values
|
110
|
+
attr_reader :values, :assn_name
|
111
|
+
|
112
|
+
def process_existing_model(value)
|
113
|
+
return false unless value.key?(:id)
|
114
|
+
model = find_model_by_value(value)
|
115
|
+
model && destroy_or_update(model, value) or add(value)
|
116
|
+
end
|
117
|
+
|
118
|
+
def destroy_or_update(model, value)
|
119
|
+
destroy(model, value) or update_attributes(model, value)
|
120
|
+
end
|
121
|
+
|
122
|
+
def add(value)
|
123
|
+
models << class_name.new(value)
|
124
|
+
end
|
125
|
+
|
126
|
+
def destroy(model, value)
|
127
|
+
wants_to_die?(value) && models.delete(model)
|
128
|
+
end
|
129
|
+
|
130
|
+
def update_attributes(model, value)
|
131
|
+
model.attributes = value
|
132
|
+
end
|
133
|
+
|
134
|
+
def wants_to_die?(value)
|
135
|
+
value.key?(:_destroy) && ArDocStore.convert_boolean(value[:_destroy])
|
136
|
+
end
|
137
|
+
|
138
|
+
def find_model_by_value(value)
|
139
|
+
models.detect { |item| item.id == value[:id] }
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|