toystore 0.8.3 → 0.9.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.
- data/.gitignore +1 -2
- data/Changelog.md +9 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +71 -0
- data/Guardfile +15 -0
- data/README.md +28 -0
- data/examples/attributes_abbreviation.rb +1 -2
- data/examples/attributes_virtual.rb +1 -2
- data/examples/identity_map.rb +7 -12
- data/examples/memcached.rb +1 -1
- data/examples/memory.rb +1 -1
- data/examples/mongo.rb +1 -1
- data/examples/redis.rb +1 -1
- data/examples/riak.rb +1 -1
- data/lib/toy.rb +40 -39
- data/lib/toy/attribute.rb +1 -6
- data/lib/toy/attributes.rb +61 -90
- data/lib/toy/caching.rb +11 -13
- data/lib/toy/callbacks.rb +12 -31
- data/lib/toy/cloneable.rb +20 -0
- data/lib/toy/collection.rb +8 -7
- data/lib/toy/dirty.rb +17 -36
- data/lib/toy/dirty_store.rb +32 -0
- data/lib/toy/equality.rb +2 -0
- data/lib/toy/extensions/boolean.rb +22 -18
- data/lib/toy/identity_map.rb +39 -62
- data/lib/toy/list.rb +23 -22
- data/lib/toy/logger.rb +2 -17
- data/lib/toy/mass_assignment_security.rb +3 -5
- data/lib/toy/middleware/identity_map.rb +23 -4
- data/lib/toy/object.rb +16 -0
- data/lib/toy/persistence.rb +72 -62
- data/lib/toy/proxies/list.rb +19 -18
- data/lib/toy/proxies/proxy.rb +7 -6
- data/lib/toy/querying.rb +2 -4
- data/lib/toy/reference.rb +28 -26
- data/lib/toy/reloadable.rb +17 -0
- data/lib/toy/serialization.rb +25 -25
- data/lib/toy/store.rb +3 -11
- data/lib/toy/validations.rb +9 -28
- data/lib/toy/version.rb +1 -1
- data/perf/reads.rb +7 -9
- data/perf/writes.rb +6 -8
- data/spec/helper.rb +3 -1
- data/spec/support/constants.rb +1 -4
- data/spec/support/identity_map_matcher.rb +5 -5
- data/spec/support/objects.rb +38 -0
- data/spec/toy/attribute_spec.rb +1 -1
- data/spec/toy/attributes_spec.rb +1 -153
- data/spec/toy/callbacks_spec.rb +1 -45
- data/spec/toy/cloneable_spec.rb +47 -0
- data/spec/toy/dirty_spec.rb +12 -44
- data/spec/toy/dirty_store_spec.rb +47 -0
- data/spec/toy/equality_spec.rb +5 -19
- data/spec/toy/extensions/boolean_spec.rb +2 -0
- data/spec/toy/identity/uuid_key_factory_spec.rb +2 -2
- data/spec/toy/identity_map_spec.rb +45 -37
- data/spec/toy/identity_spec.rb +1 -1
- data/spec/toy/inspect_spec.rb +1 -1
- data/spec/toy/lists_spec.rb +20 -5
- data/spec/toy/logger_spec.rb +1 -29
- data/spec/toy/mass_assignment_security_spec.rb +16 -5
- data/spec/toy/middleware/identity_map_spec.rb +68 -2
- data/spec/toy/persistence_spec.rb +88 -30
- data/spec/toy/reference_spec.rb +0 -1
- data/spec/toy/references_spec.rb +20 -0
- data/spec/toy/reloadable_spec.rb +81 -0
- data/spec/toy/serialization_spec.rb +1 -110
- data/spec/toy/validations_spec.rb +0 -21
- data/spec/toy_spec.rb +4 -5
- data/test/lint_test.rb +1 -1
- metadata +21 -26
- data/.autotest +0 -11
- data/LOGGING.rdoc +0 -12
- data/README.rdoc +0 -27
- data/examples/models.rb +0 -51
- data/lib/toy/dolly.rb +0 -30
- data/lib/toy/embedded_list.rb +0 -45
- data/lib/toy/embedded_lists.rb +0 -68
- data/lib/toy/index.rb +0 -74
- data/lib/toy/indices.rb +0 -56
- data/lib/toy/proxies/embedded_list.rb +0 -79
- data/spec/toy/dolly_spec.rb +0 -76
- data/spec/toy/embedded_list_spec.rb +0 -607
- data/spec/toy/embedded_lists_spec.rb +0 -172
- data/spec/toy/index_spec.rb +0 -230
- data/spec/toy/indices_spec.rb +0 -141
- data/specs.watchr +0 -52
data/lib/toy/logger.rb
CHANGED
@@ -3,28 +3,13 @@ module Toy
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
-
OperationsToLogValueFor = [:get, :set, :del]
|
7
|
-
|
8
6
|
def logger
|
9
7
|
Toy.logger
|
10
8
|
end
|
11
|
-
|
12
|
-
def log_operation(operation, model, adapter, key, value=nil)
|
13
|
-
if logger && logger.debug?
|
14
|
-
logger.debug("TOYSTORE #{operation.to_s.upcase} #{model} :#{adapter.name} #{key.inspect}")
|
15
|
-
logger.debug(" #{value.inspect}") if !value.nil? && OperationsToLogValueFor.include?(operation)
|
16
|
-
end
|
17
|
-
end
|
18
9
|
end
|
19
10
|
|
20
|
-
|
21
|
-
|
22
|
-
Toy.logger
|
23
|
-
end
|
24
|
-
|
25
|
-
def log_operation(*args)
|
26
|
-
self.class.log_operation(*args)
|
27
|
-
end
|
11
|
+
def logger
|
12
|
+
Toy.logger
|
28
13
|
end
|
29
14
|
end
|
30
15
|
end
|
@@ -3,11 +3,9 @@ module Toy
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
include ActiveModel::MassAssignmentSecurity
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
super(attrs)
|
10
|
-
end
|
6
|
+
def attributes=(attrs, guard_protected_attributes=true)
|
7
|
+
attrs = sanitize_for_mass_assignment(attrs || {}) if guard_protected_attributes
|
8
|
+
super(attrs)
|
11
9
|
end
|
12
10
|
end
|
13
11
|
end
|
@@ -1,15 +1,34 @@
|
|
1
1
|
module Toy
|
2
2
|
module Middleware
|
3
3
|
class IdentityMap
|
4
|
+
class Body
|
5
|
+
def initialize(target, original)
|
6
|
+
@target = target
|
7
|
+
@original = original
|
8
|
+
end
|
9
|
+
|
10
|
+
def each(&block)
|
11
|
+
@target.each(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def close
|
15
|
+
@target.close if @target.respond_to?(:close)
|
16
|
+
ensure
|
17
|
+
Toy::IdentityMap.enabled = @original
|
18
|
+
Toy::IdentityMap.clear
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
4
22
|
def initialize(app)
|
5
23
|
@app = app
|
6
24
|
end
|
7
25
|
|
8
26
|
def call(env)
|
9
|
-
Toy.
|
10
|
-
|
11
|
-
|
12
|
-
|
27
|
+
Toy::IdentityMap.clear
|
28
|
+
enabled = Toy::IdentityMap.enabled
|
29
|
+
Toy::IdentityMap.enabled = true
|
30
|
+
status, headers, body = @app.call(env)
|
31
|
+
[status, headers, Body.new(body, enabled)]
|
13
32
|
end
|
14
33
|
end
|
15
34
|
end
|
data/lib/toy/object.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Toy
|
2
|
+
module Object
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
extend ActiveModel::Naming
|
7
|
+
include ActiveModel::Conversion
|
8
|
+
include Attributes
|
9
|
+
include Cloneable
|
10
|
+
include Dirty
|
11
|
+
include Equality
|
12
|
+
include Inspect
|
13
|
+
include Logger
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/toy/persistence.rb
CHANGED
@@ -3,15 +3,20 @@ module Toy
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
def adapter(name=nil, client=nil, options={})
|
7
|
+
missing_client = !name.nil? && client.nil?
|
8
|
+
raise(ArgumentError, 'Client is required') if missing_client
|
9
|
+
|
10
|
+
needs_default_adapter = name.nil? && client.nil?
|
11
|
+
assigning_adapter = !name.nil? && !client.nil?
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
if needs_default_adapter
|
14
|
+
@adapter ||= Adapter[:memory].new({}, options)
|
15
|
+
elsif assigning_adapter
|
16
|
+
@adapter = Adapter[name].new(client, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
@adapter
|
15
20
|
end
|
16
21
|
|
17
22
|
def create(attrs={})
|
@@ -25,75 +30,80 @@ module Toy
|
|
25
30
|
def destroy(*ids)
|
26
31
|
ids.each { |id| get(id).try(:destroy) }
|
27
32
|
end
|
33
|
+
end
|
28
34
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
35
|
+
def adapter
|
36
|
+
self.class.adapter
|
37
|
+
end
|
33
38
|
|
34
|
-
|
35
|
-
|
36
|
-
|
39
|
+
def initialize(attrs={})
|
40
|
+
@_new_record = true
|
41
|
+
super
|
37
42
|
end
|
38
43
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
44
|
+
def initialize_from_database(attrs={})
|
45
|
+
@_new_record = false
|
46
|
+
initialize_attributes_with_defaults
|
47
|
+
send("attributes=", attrs, false)
|
48
|
+
self
|
49
|
+
end
|
43
50
|
|
44
|
-
|
45
|
-
|
46
|
-
|
51
|
+
def initialize_copy(other)
|
52
|
+
super
|
53
|
+
@_new_record = true
|
54
|
+
@_destroyed = false
|
55
|
+
end
|
47
56
|
|
48
|
-
|
49
|
-
|
50
|
-
|
57
|
+
def new_record?
|
58
|
+
@_new_record == true
|
59
|
+
end
|
51
60
|
|
52
|
-
|
53
|
-
|
54
|
-
|
61
|
+
def destroyed?
|
62
|
+
@_destroyed == true
|
63
|
+
end
|
55
64
|
|
56
|
-
|
57
|
-
|
58
|
-
|
65
|
+
def persisted?
|
66
|
+
!new_record? && !destroyed?
|
67
|
+
end
|
59
68
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
69
|
+
def save(*)
|
70
|
+
new_record? ? create : update
|
71
|
+
end
|
64
72
|
|
65
|
-
|
66
|
-
|
67
|
-
|
73
|
+
def update_attributes(attrs)
|
74
|
+
self.attributes = attrs
|
75
|
+
save
|
76
|
+
end
|
68
77
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
store.delete(id)
|
73
|
-
end
|
78
|
+
def destroy
|
79
|
+
delete
|
80
|
+
end
|
74
81
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
82
|
+
def delete
|
83
|
+
@_destroyed = true
|
84
|
+
adapter.delete(id)
|
85
|
+
end
|
79
86
|
|
80
|
-
|
81
|
-
persist!
|
82
|
-
end
|
87
|
+
private
|
83
88
|
|
84
|
-
|
85
|
-
|
86
|
-
|
89
|
+
def create
|
90
|
+
persist!
|
91
|
+
end
|
87
92
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
93
|
+
def update
|
94
|
+
persist!
|
95
|
+
end
|
96
|
+
|
97
|
+
def persist
|
98
|
+
@_new_record = false
|
99
|
+
end
|
100
|
+
|
101
|
+
def persist!
|
102
|
+
attrs = persisted_attributes
|
103
|
+
attrs.delete('id') # no need to persist id as that is key
|
104
|
+
adapter.write(id, attrs)
|
105
|
+
persist
|
106
|
+
true
|
97
107
|
end
|
98
108
|
end
|
99
109
|
end
|
data/lib/toy/proxies/list.rb
CHANGED
@@ -70,28 +70,29 @@ module Toy
|
|
70
70
|
end
|
71
71
|
|
72
72
|
private
|
73
|
-
def find_target
|
74
|
-
return [] if target_ids.blank?
|
75
|
-
proxy_class.get_multi(target_ids)
|
76
|
-
end
|
77
73
|
|
78
|
-
|
79
|
-
|
80
|
-
|
74
|
+
def find_target
|
75
|
+
return [] if target_ids.blank?
|
76
|
+
proxy_class.get_multi(target_ids)
|
77
|
+
end
|
81
78
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
79
|
+
def target_ids
|
80
|
+
proxy_owner.send(proxy_key)
|
81
|
+
end
|
82
|
+
|
83
|
+
def target_ids=(value)
|
84
|
+
ids = value.map do |item|
|
85
|
+
if item.is_a?(proxy_class)
|
86
|
+
item.id
|
87
|
+
elsif item.is_a?(Hash)
|
88
|
+
item['id']
|
89
|
+
else
|
90
|
+
item
|
91
91
|
end
|
92
|
-
proxy_owner.send(:"#{proxy_key}=", ids)
|
93
|
-
reset
|
94
92
|
end
|
93
|
+
proxy_owner.send(:"#{proxy_key}=", ids)
|
94
|
+
reset
|
95
|
+
end
|
95
96
|
end
|
96
97
|
end
|
97
98
|
end
|
data/lib/toy/proxies/proxy.rb
CHANGED
@@ -47,13 +47,14 @@ module Toy
|
|
47
47
|
end
|
48
48
|
|
49
49
|
private
|
50
|
-
def find_target
|
51
|
-
raise('Not Implemented')
|
52
|
-
end
|
53
50
|
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
def find_target
|
52
|
+
raise('Not Implemented')
|
53
|
+
end
|
54
|
+
|
55
|
+
def method_missing(method, *args, &block)
|
56
|
+
target.send(method, *args, &block)
|
57
|
+
end
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
data/lib/toy/querying.rb
CHANGED
@@ -4,8 +4,7 @@ module Toy
|
|
4
4
|
|
5
5
|
module ClassMethods
|
6
6
|
def get(id)
|
7
|
-
|
8
|
-
load(id, store.read(id))
|
7
|
+
load(id, adapter.read(id))
|
9
8
|
end
|
10
9
|
|
11
10
|
def get!(id)
|
@@ -25,8 +24,7 @@ module Toy
|
|
25
24
|
end
|
26
25
|
|
27
26
|
def key?(id)
|
28
|
-
|
29
|
-
store.key?(id)
|
27
|
+
adapter.key?(id)
|
30
28
|
end
|
31
29
|
alias :has_key? :key?
|
32
30
|
|
data/lib/toy/reference.rb
CHANGED
@@ -95,40 +95,42 @@ module Toy
|
|
95
95
|
end
|
96
96
|
|
97
97
|
private
|
98
|
-
def assert_type(record)
|
99
|
-
unless record.instance_of?(proxy_class)
|
100
|
-
raise(ArgumentError, "#{proxy_class} expected, but was #{record.class}")
|
101
|
-
end
|
102
|
-
end
|
103
98
|
|
104
|
-
|
105
|
-
|
99
|
+
def assert_type(record)
|
100
|
+
unless record.instance_of?(proxy_class)
|
101
|
+
raise(ArgumentError, "#{proxy_class} expected, but was #{record.class}")
|
106
102
|
end
|
103
|
+
end
|
107
104
|
|
108
|
-
|
109
|
-
|
110
|
-
|
105
|
+
def target_id
|
106
|
+
proxy_owner.send(proxy_key)
|
107
|
+
end
|
111
108
|
|
112
|
-
|
113
|
-
|
114
|
-
|
109
|
+
def target_id=(value)
|
110
|
+
proxy_owner.send("#{proxy_key}=", value)
|
111
|
+
end
|
112
|
+
|
113
|
+
def method_missing(method, *args, &block)
|
114
|
+
target.send(method, *args, &block)
|
115
|
+
end
|
115
116
|
end
|
116
117
|
|
117
118
|
private
|
118
|
-
def create_accessors
|
119
|
-
model.class_eval """
|
120
|
-
def #{name}
|
121
|
-
#{instance_variable} ||= self.class.references[:#{name}].new_proxy(self)
|
122
|
-
end
|
123
119
|
|
124
|
-
|
125
|
-
|
126
|
-
|
120
|
+
def create_accessors
|
121
|
+
model.class_eval """
|
122
|
+
def #{name}
|
123
|
+
#{instance_variable} ||= self.class.references[:#{name}].new_proxy(self)
|
124
|
+
end
|
127
125
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
126
|
+
def #{name}=(record)
|
127
|
+
#{name}.replace(record)
|
128
|
+
end
|
129
|
+
|
130
|
+
def #{name}?
|
131
|
+
#{name}.present?
|
132
|
+
end
|
133
|
+
"""
|
134
|
+
end
|
133
135
|
end
|
134
136
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Toy
|
2
|
+
module Reloadable
|
3
|
+
def reload
|
4
|
+
if attrs = adapter.read(id)
|
5
|
+
attrs['id'] = id
|
6
|
+
instance_variables.each { |ivar| instance_variable_set(ivar, nil) }
|
7
|
+
initialize_attributes_with_defaults
|
8
|
+
send(:attributes=, attrs, new_record?)
|
9
|
+
self.class.lists.each_key { |name| send(name).reset }
|
10
|
+
self.class.references.each_key { |name| send(name).reset }
|
11
|
+
else
|
12
|
+
raise NotFound.new(id)
|
13
|
+
end
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|