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
@@ -0,0 +1,52 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module Types
|
3
|
+
class EmbedsMany < ActiveModel::Type::Value
|
4
|
+
attr_accessor :class_name
|
5
|
+
|
6
|
+
def initialize(class_name)
|
7
|
+
@class_name = class_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def cast(values)
|
11
|
+
@class_name = @class_name.constantize if class_name.respond_to?(:constantize)
|
12
|
+
collection = EmbeddedCollection.new
|
13
|
+
values && values.each do |value|
|
14
|
+
collection << if value.nil?
|
15
|
+
value
|
16
|
+
elsif value.kind_of?(class_name)
|
17
|
+
value
|
18
|
+
elsif value.respond_to?(:to_hash)
|
19
|
+
class_name.new value
|
20
|
+
else
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
collection
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialize(values)
|
28
|
+
if values.nil?
|
29
|
+
nil
|
30
|
+
elsif values.respond_to?(:each)
|
31
|
+
values.map { |value|
|
32
|
+
if value.nil?
|
33
|
+
nil
|
34
|
+
elsif value.kind_of?(class_name)
|
35
|
+
value.serializable_hash
|
36
|
+
else
|
37
|
+
cast(value).serializable_hash
|
38
|
+
end
|
39
|
+
}.compact
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def deserialize(value)
|
44
|
+
cast(value)
|
45
|
+
end
|
46
|
+
|
47
|
+
def changed_in_place?(raw_old_value, new_value)
|
48
|
+
serialize(new_value) != raw_old_value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ArDocStore
|
2
|
+
module Types
|
3
|
+
class EmbedsOne < ActiveModel::Type::Value
|
4
|
+
attr_accessor :class_name
|
5
|
+
|
6
|
+
def initialize(class_name)
|
7
|
+
@class_name = class_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def cast(value)
|
11
|
+
@class_name = @class_name.constantize if class_name.respond_to?(:constantize)
|
12
|
+
if value.nil?
|
13
|
+
value
|
14
|
+
elsif value.kind_of?(class_name)
|
15
|
+
value
|
16
|
+
elsif value.respond_to?(:to_hash)
|
17
|
+
class_name.new value
|
18
|
+
else
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def serialize(value)
|
24
|
+
if value.nil?
|
25
|
+
nil
|
26
|
+
elsif value.kind_of?(class_name)
|
27
|
+
value.serializable_hash
|
28
|
+
else
|
29
|
+
cast(value).serializable_hash
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def deserialize(value)
|
34
|
+
cast(value)
|
35
|
+
end
|
36
|
+
|
37
|
+
def changed_in_place?(raw_old_value, new_value)
|
38
|
+
serialize(new_value) != raw_old_value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/ar_doc_store/version.rb
CHANGED
@@ -21,5 +21,9 @@ class ArrayAttributeTest < MiniTest::Test
|
|
21
21
|
assert_equal true, b.architects?
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
def test_persistence
|
25
|
+
b = Building.new name: 'Test', stories: 5, architects: %W{Bob John}
|
26
|
+
assert b.save
|
27
|
+
assert_equal b.architects, Building.find(b.id).architects
|
28
|
+
end
|
25
29
|
end
|
@@ -32,5 +32,11 @@ class BooleanAttributeTest < MiniTest::Test
|
|
32
32
|
b.finished = '1'
|
33
33
|
assert_equal true, b.finished
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
|
+
def test_persistence
|
37
|
+
b = Building.new name: 'Test', finished: true
|
38
|
+
assert b.save
|
39
|
+
assert_equal true, Building.find(b.id).finished?
|
40
|
+
end
|
41
|
+
|
36
42
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative './../test_helper'
|
2
|
+
|
3
|
+
class DateAttributeTest < MiniTest::Test
|
4
|
+
|
5
|
+
def test_attribute_on_model_init
|
6
|
+
finished_on = Date.new(1984, 3, 6)
|
7
|
+
b = Building.new finished_on: finished_on
|
8
|
+
assert finished_on == b.finished_on
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_attribute_on_existing_model
|
12
|
+
finished_on = Date.new(1984, 3, 6)
|
13
|
+
b = Building.new
|
14
|
+
b.finished_on = finished_on
|
15
|
+
assert finished_on == b.finished_on
|
16
|
+
assert b.finished_on_changed?
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_question_mark_method
|
20
|
+
finished_on = Date.new(1984, 3, 6)
|
21
|
+
b = Building.new finished_on: finished_on
|
22
|
+
assert_equal true, b.finished_on?
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_conversion
|
26
|
+
finished_on = Date.new(1984, 3, 6)
|
27
|
+
b = Building.new finished_on: finished_on.to_s
|
28
|
+
assert_kind_of Date, b.finished_on
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_no_op
|
32
|
+
b = Building.new
|
33
|
+
assert_nil b.finished_on
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_multiparameter_assignment
|
37
|
+
finished_on = {
|
38
|
+
"finished_on(2i)" => "4",
|
39
|
+
"finished_on(1i)" => "2014",
|
40
|
+
"finished_on(3i)" => "21",
|
41
|
+
}
|
42
|
+
b = Building.new finished_on
|
43
|
+
assert_equal Date.new(2014, 4, 21), b.finished_on
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_persistence
|
47
|
+
finished_on = Date.new(2014, 4, 21)
|
48
|
+
b = Building.new finished_on: finished_on
|
49
|
+
assert b.save
|
50
|
+
assert_equal Date.new(2014, 4, 21), Building.find(b.id).finished_on
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative './../test_helper'
|
2
|
+
|
3
|
+
class DatetimeAttributeTest < MiniTest::Test
|
4
|
+
|
5
|
+
def test_attribute_on_model_init
|
6
|
+
inspected_at = Time.new(1984, 3, 6)
|
7
|
+
b = Building.new inspected_at: inspected_at
|
8
|
+
assert inspected_at == b.inspected_at
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_attribute_on_existing_model
|
12
|
+
inspected_at = Time.new(1984, 3, 6)
|
13
|
+
b = Building.new
|
14
|
+
b.inspected_at = inspected_at
|
15
|
+
assert inspected_at == b.inspected_at
|
16
|
+
assert b.inspected_at_changed?
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_question_mark_method
|
20
|
+
inspected_at = Time.new(1984, 3, 6)
|
21
|
+
b = Building.new inspected_at: inspected_at
|
22
|
+
assert_equal true, b.inspected_at?
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_conversion
|
26
|
+
inspected_at = Time.new(1984, 3, 6)
|
27
|
+
b = Building.new inspected_at: inspected_at.to_s
|
28
|
+
assert_kind_of Time, b.inspected_at
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_no_op
|
32
|
+
b = Building.new
|
33
|
+
assert_nil b.inspected_at
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_multiparameter_assignment
|
37
|
+
inspected_at = {
|
38
|
+
"inspected_at(2i)" => "4",
|
39
|
+
"inspected_at(4i)" => "12",
|
40
|
+
"inspected_at(1i)" => "2014",
|
41
|
+
"inspected_at(3i)" => "21",
|
42
|
+
"inspected_at(5i)" => "53",
|
43
|
+
}
|
44
|
+
b = Building.new inspected_at
|
45
|
+
assert_equal DateTime.new(2014, 4, 21, 12, 53), b.inspected_at
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_persistence
|
49
|
+
inspected_at = DateTime.new(2014, 4, 21, 12, 53)
|
50
|
+
b = Building.new inspected_at: inspected_at
|
51
|
+
assert b.save
|
52
|
+
assert_equal DateTime.new(2014, 4, 21, 12, 53), Building.find(b.id).inspected_at
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative './../test_helper'
|
2
|
+
|
3
|
+
class DecimalAttributeTest < MiniTest::Test
|
4
|
+
|
5
|
+
def test_attribute_on_model_init
|
6
|
+
b = Building.new cost: 5.42
|
7
|
+
assert_equal 5.42, b.cost
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_attribute_on_existing_model
|
11
|
+
b = Building.new
|
12
|
+
b.cost = 5.42
|
13
|
+
assert_equal 5.42, b.cost
|
14
|
+
assert b.cost_changed?
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_question_mark_method
|
18
|
+
b = Building.new cost: 5.42
|
19
|
+
assert_equal true, b.cost?
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_type_conversion_on_init
|
23
|
+
b = Building.new cost: '5.42'
|
24
|
+
assert_equal 5.42, b.cost
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_type_conversion_on_existing
|
28
|
+
b = Building.new
|
29
|
+
b.cost = '5.42'
|
30
|
+
assert_equal 5.42, b.cost
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_persistence
|
34
|
+
b = Building.new name: 'Test', cost: 87.4
|
35
|
+
assert b.save
|
36
|
+
assert_equal 87.4, Building.find(b.id).cost.to_f
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative './../test_helper'
|
2
|
+
|
3
|
+
class EmbedsManyAttributeTest < MiniTest::Test
|
4
|
+
|
5
|
+
def test_initialized_on_model_init
|
6
|
+
r = Restroom.new name: 'Foo'
|
7
|
+
b = Building.new restrooms: [r]
|
8
|
+
assert_equal r.name, b.restrooms.first.name
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_hash_on_model_init
|
12
|
+
r = { name: 'Foo' }
|
13
|
+
b = Building.new restrooms: [r]
|
14
|
+
assert_equal r[:name], b.restrooms.first.name
|
15
|
+
assert_equal b, b.restrooms.first.parent.parent
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_persistence
|
19
|
+
r = { name: 'Foo' }
|
20
|
+
b = Building.new restrooms: [r]
|
21
|
+
b.save
|
22
|
+
assert_equal r[:name], Building.find(b.id).restrooms.first.name
|
23
|
+
assert_equal b, b.restrooms.first.parent.parent
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_build_method
|
27
|
+
b = Building.new
|
28
|
+
b.build_restroom name: 'Test'
|
29
|
+
assert_equal 'Test', b.restrooms.first.name
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_ensure_method
|
33
|
+
b = Building.new
|
34
|
+
b.ensure_restroom
|
35
|
+
assert !!b.restrooms.first
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_autosave
|
39
|
+
a = Building.new name: 'Foo'
|
40
|
+
r = a.build_restroom
|
41
|
+
r.name = 'Bar'
|
42
|
+
a.save
|
43
|
+
b = Building.find(a.id)
|
44
|
+
assert_equal r.name, b.restrooms.first.name
|
45
|
+
b.restrooms.first.name = 'Baz'
|
46
|
+
b.save
|
47
|
+
c = Building.find(a.id)
|
48
|
+
assert_equal 'Baz', c.restrooms.first.name
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_attributes_method
|
52
|
+
a = Building.new name: 'Foo', restrooms_attributes: { 0 => { name: 'Bar' } }
|
53
|
+
assert_equal 'Bar', a.restrooms.first.name
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_dirty_on_init
|
57
|
+
b = Building.new name: 'Foo', restrooms: [{ name: 'Foo' }]
|
58
|
+
assert b.restrooms.first.name_changed?
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_dirty_persisted
|
62
|
+
a = Building.create name: 'Foo', restrooms: [{ name: 'Foo' }]
|
63
|
+
b = Building.find a.id
|
64
|
+
assert !b.restrooms.first.name_changed?
|
65
|
+
b.restrooms.first.name = 'Bar'
|
66
|
+
assert_equal 'Bar', b.restrooms.first.name
|
67
|
+
assert b.restrooms.first.name_changed?
|
68
|
+
assert_equal 'Foo', b.restrooms.first.name_was
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_rejects_all_blank
|
72
|
+
a = Building.new name: 'Foo'
|
73
|
+
a.restrooms_attributes = { 0 => { name: nil }}
|
74
|
+
a.save
|
75
|
+
b = Building.find a.id
|
76
|
+
assert_equal 0, b.restrooms.size
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require_relative './../test_helper'
|
2
|
+
|
3
|
+
class EmbedsOneAttributeTest < MiniTest::Test
|
4
|
+
|
5
|
+
def test_initialized_on_model_init
|
6
|
+
entrance = Entrance.new name: 'Foo'
|
7
|
+
b = Building.new entrance: entrance
|
8
|
+
assert_equal entrance.name, b.entrance.name
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_hash_on_model_init
|
12
|
+
entrance = { name: 'Foo' }
|
13
|
+
b = Building.new entrance: entrance
|
14
|
+
assert_equal entrance[:name], b.entrance.name
|
15
|
+
assert_equal b, b.entrance.parent
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_persistence
|
19
|
+
entrance = { name: 'Foo' }
|
20
|
+
b = Building.new entrance: entrance
|
21
|
+
b.save
|
22
|
+
assert_equal entrance[:name], Building.find(b.id).entrance.name
|
23
|
+
assert_equal b, b.entrance.parent
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_build_method
|
27
|
+
b = Building.new
|
28
|
+
b.build_entrance name: 'Test'
|
29
|
+
assert_equal 'Test', b.entrance.name
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_ensure_method
|
33
|
+
b = Building.new
|
34
|
+
b.ensure_entrance
|
35
|
+
assert !!b.entrance
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_autosave
|
39
|
+
a = Building.new name: 'Foo'
|
40
|
+
a.build_entrance
|
41
|
+
a.entrance.name = 'Bar'
|
42
|
+
a.save
|
43
|
+
b = Building.find(a.id)
|
44
|
+
assert_equal a.entrance.name, b.entrance.name
|
45
|
+
b.entrance.name = 'Baz'
|
46
|
+
assert b.entrance_changed?
|
47
|
+
assert b.entrance.name_changed?
|
48
|
+
assert_equal b.data['entrance']['name'], b.entrance.name
|
49
|
+
b.save
|
50
|
+
c = Building.find(a.id)
|
51
|
+
assert_equal b.data, c.data
|
52
|
+
assert_equal 'Baz', c.entrance.name
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_attributes_method
|
56
|
+
a = Building.new name: 'Foo', entrance_attributes: { name: 'Bar' }
|
57
|
+
assert_equal 'Bar', a.entrance.name
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_class_name_option
|
61
|
+
a = Building.new main_entrance: { name: 'Foo' }
|
62
|
+
assert a.main_entrance.is_a?(Entrance)
|
63
|
+
assert_equal 'Foo', a.main_entrance.name
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_dirty_on_init
|
67
|
+
b = Building.new name: 'Foo', entrance: { name: 'Foo' }
|
68
|
+
assert b.entrance.name_changed?
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_dirty_persisted
|
72
|
+
a = Building.create name: 'Foo', entrance: { name: 'Foo' }
|
73
|
+
b = Building.find a.id
|
74
|
+
assert b.entrance.id.present?
|
75
|
+
assert !b.entrance.name_changed?
|
76
|
+
b.entrance.name = 'Bar'
|
77
|
+
assert b.entrance.name_changed?
|
78
|
+
assert_equal 'Foo', b.entrance.name_was
|
79
|
+
end
|
80
|
+
end
|
@@ -59,4 +59,9 @@ class EnumerationAttributeTest < MiniTest::Test
|
|
59
59
|
assert_equal true, b.strict_multi_enumeration?
|
60
60
|
end
|
61
61
|
|
62
|
+
def test_persistence
|
63
|
+
b = Building.new name: 'Test', strict_multi_enumeration: %w{glad bad}
|
64
|
+
assert b.save
|
65
|
+
assert_equal %w{glad bad}, Building.find(b.id).strict_multi_enumeration
|
66
|
+
end
|
62
67
|
end
|
@@ -29,5 +29,10 @@ class FloatAttributeTest < MiniTest::Test
|
|
29
29
|
b.height = '5.42'
|
30
30
|
assert_equal 5.42, b.height
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
|
+
def test_persistence
|
34
|
+
b = Building.new name: 'Test', height: 87.4
|
35
|
+
assert b.save
|
36
|
+
assert_equal 87.4, Building.find(b.id).height
|
37
|
+
end
|
33
38
|
end
|