zermelo 1.0.1 → 1.1.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/.rspec +1 -1
- data/.travis.yml +3 -5
- data/CHANGELOG.md +8 -2
- data/lib/zermelo/associations/belongs_to.rb +3 -3
- data/lib/zermelo/associations/has_and_belongs_to_many.rb +3 -3
- data/lib/zermelo/associations/has_many.rb +3 -3
- data/lib/zermelo/associations/has_one.rb +3 -3
- data/lib/zermelo/associations/has_sorted_set.rb +4 -4
- data/lib/zermelo/associations/index.rb +1 -2
- data/lib/zermelo/associations/unique_index.rb +1 -2
- data/lib/zermelo/backends/base.rb +1 -1
- data/lib/zermelo/backends/influxdb_backend.rb +29 -18
- data/lib/zermelo/backends/redis_backend.rb +106 -6
- data/lib/zermelo/filters/base.rb +34 -57
- data/lib/zermelo/filters/influxdb_filter.rb +22 -70
- data/lib/zermelo/filters/redis_filter.rb +35 -482
- data/lib/zermelo/filters/steps/list_step.rb +79 -0
- data/lib/zermelo/filters/steps/set_step.rb +176 -0
- data/lib/zermelo/filters/steps/sort_step.rb +85 -0
- data/lib/zermelo/filters/steps/sorted_set_step.rb +156 -0
- data/lib/zermelo/records/class_methods.rb +16 -4
- data/lib/zermelo/records/influxdb_record.rb +2 -0
- data/lib/zermelo/records/instance_methods.rb +4 -4
- data/lib/zermelo/records/key.rb +2 -0
- data/lib/zermelo/version.rb +1 -1
- data/lib/zermelo.rb +9 -1
- data/spec/lib/zermelo/records/influxdb_record_spec.rb +186 -10
- data/spec/lib/zermelo/records/redis_record_spec.rb +11 -4
- data/spec/spec_helper.rb +12 -10
- metadata +5 -11
- data/lib/zermelo/filters/steps/diff_range_step.rb +0 -17
- data/lib/zermelo/filters/steps/diff_step.rb +0 -17
- data/lib/zermelo/filters/steps/intersect_range_step.rb +0 -17
- data/lib/zermelo/filters/steps/intersect_step.rb +0 -17
- data/lib/zermelo/filters/steps/limit_step.rb +0 -17
- data/lib/zermelo/filters/steps/offset_step.rb +0 -17
- data/lib/zermelo/filters/steps/union_range_step.rb +0 -17
- data/lib/zermelo/filters/steps/union_step.rb +0 -17
- data/lib/zermelo/records/collection.rb +0 -14
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'zermelo/filters/steps/base_step'
|
2
|
+
|
3
|
+
# NB: temp keys for now are bare redis keys, should be full Key objects
|
4
|
+
module Zermelo
|
5
|
+
module Filters
|
6
|
+
class Steps
|
7
|
+
class SetStep < Zermelo::Filters::Steps::BaseStep
|
8
|
+
def self.accepted_types
|
9
|
+
[:set, :sorted_set] # TODO should allow :list as well
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.returns_type
|
13
|
+
:set
|
14
|
+
end
|
15
|
+
|
16
|
+
REDIS_SHORTCUTS = {
|
17
|
+
:ids => proc {|key| Zermelo.redis.smembers(key) },
|
18
|
+
:count => proc {|key| Zermelo.redis.scard(key) },
|
19
|
+
:exists? => proc {|key, id| Zermelo.redis.sismember(key, id) }
|
20
|
+
}
|
21
|
+
|
22
|
+
def resolve(backend, associated_class, opts = {})
|
23
|
+
|
24
|
+
case backend
|
25
|
+
when Zermelo::Backends::RedisBackend
|
26
|
+
source = opts[:source]
|
27
|
+
idx_attrs = opts[:index_attrs]
|
28
|
+
attr_types = opts[:attr_types]
|
29
|
+
temp_keys = opts[:temp_keys]
|
30
|
+
|
31
|
+
source_keys = @attributes.inject([]) do |memo, (att, value)|
|
32
|
+
|
33
|
+
val = value.is_a?(Set) ? value.to_a : value
|
34
|
+
|
35
|
+
if :id.eql?(att)
|
36
|
+
ts = associated_class.send(:temp_key, :set)
|
37
|
+
temp_keys << ts
|
38
|
+
Zermelo.redis.sadd(backend.key_to_redis_key(ts), val)
|
39
|
+
memo << ts
|
40
|
+
else
|
41
|
+
idx_class = idx_attrs[att.to_s]
|
42
|
+
raise "'#{att}' property is not indexed" if idx_class.nil?
|
43
|
+
|
44
|
+
if val.is_a?(Enumerable)
|
45
|
+
conditions_set = associated_class.send(:temp_key, :set)
|
46
|
+
r_conditions_set = backend.key_to_redis_key(conditions_set)
|
47
|
+
|
48
|
+
backend.temp_key_wrap do |conditions_temp_keys|
|
49
|
+
index_keys = val.collect {|v|
|
50
|
+
il = backend.index_lookup(att, associated_class,
|
51
|
+
idx_class, v, attr_types[att], conditions_temp_keys)
|
52
|
+
backend.key_to_redis_key(il)
|
53
|
+
}
|
54
|
+
|
55
|
+
Zermelo.redis.sunionstore(r_conditions_set, *index_keys)
|
56
|
+
end
|
57
|
+
memo << conditions_set
|
58
|
+
else
|
59
|
+
memo << backend.index_lookup(att, associated_class,
|
60
|
+
idx_class, val, attr_types[att], temp_keys)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
memo
|
65
|
+
end
|
66
|
+
|
67
|
+
case source.type
|
68
|
+
when :sorted_set
|
69
|
+
Zermelo::Filters::Steps::SortedSetStep.evaluate(backend,
|
70
|
+
@options[:op], associated_class, source, source_keys, temp_keys, opts)
|
71
|
+
when :set
|
72
|
+
self.class.evaluate(backend, @options[:op], associated_class,
|
73
|
+
source, source_keys, temp_keys, opts)
|
74
|
+
end
|
75
|
+
|
76
|
+
when Zermelo::Backends::InfluxDBBackend
|
77
|
+
query = ''
|
78
|
+
|
79
|
+
unless opts[:first].is_a?(TrueClass)
|
80
|
+
case @options[:op]
|
81
|
+
when :intersect, :diff
|
82
|
+
query += ' AND '
|
83
|
+
when :union
|
84
|
+
query += ' OR '
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
case @options[:op]
|
89
|
+
when :intersect, :union
|
90
|
+
query += @attributes.collect {|k, v|
|
91
|
+
op, value = case v
|
92
|
+
when String
|
93
|
+
["=~", "/^#{Regexp.escape(v).gsub(/\\\\/, "\\")}$/"]
|
94
|
+
else
|
95
|
+
["=", "'#{v}'"]
|
96
|
+
end
|
97
|
+
|
98
|
+
"#{k} #{op} #{value}"
|
99
|
+
}.join(' AND ')
|
100
|
+
|
101
|
+
when :diff
|
102
|
+
query += @attributes.collect {|k, v|
|
103
|
+
op, value = case v
|
104
|
+
when String
|
105
|
+
["!~", "/^#{Regexp.escape(v).gsub(/\\\\/, "\\")}$/"]
|
106
|
+
else
|
107
|
+
["!=", "'#{v}'"]
|
108
|
+
end
|
109
|
+
|
110
|
+
"#{k} #{op} #{value}"
|
111
|
+
}.join(' AND ')
|
112
|
+
else
|
113
|
+
raise "Unhandled filter operation '#{@options[:op]}'"
|
114
|
+
end
|
115
|
+
|
116
|
+
query += ")"
|
117
|
+
|
118
|
+
query
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.evaluate(backend, op, associated_class, source, source_keys, temp_keys, opts = {})
|
123
|
+
shortcut = opts[:shortcut]
|
124
|
+
|
125
|
+
r_source_key = backend.key_to_redis_key(source)
|
126
|
+
r_source_keys = source_keys.collect {|sk| backend.key_to_redis_key(sk) }
|
127
|
+
|
128
|
+
if :ids.eql?(shortcut)
|
129
|
+
case op
|
130
|
+
when :union
|
131
|
+
backend.temp_key_wrap do |shortcut_temp_keys|
|
132
|
+
dest_set = associated_class.send(:temp_key, :set)
|
133
|
+
shortcut_temp_keys << dest_set
|
134
|
+
r_dest_set = backend.key_to_redis_key(dest_set)
|
135
|
+
|
136
|
+
Zermelo.redis.sinterstore(r_dest_set, *r_source_keys)
|
137
|
+
Zermelo.redis.sunion(r_dest_set, r_source_key)
|
138
|
+
end
|
139
|
+
when :intersect
|
140
|
+
Zermelo.redis.sinter(r_source_key, *r_source_keys)
|
141
|
+
when :diff
|
142
|
+
backend.temp_key_wrap do |shortcut_temp_keys|
|
143
|
+
dest_set = associated_class.send(:temp_key, :set)
|
144
|
+
shortcut_temp_keys << dest_set
|
145
|
+
r_dest_set = backend.key_to_redis_key(dest_set)
|
146
|
+
|
147
|
+
Zermelo.redis.sinterstore(r_dest_set, *r_source_keys)
|
148
|
+
Zermelo.redis.sdiff(r_source_key, r_dest_set)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
else
|
152
|
+
dest_set = associated_class.send(:temp_key, :set)
|
153
|
+
r_dest_set = backend.key_to_redis_key(dest_set)
|
154
|
+
temp_keys << dest_set
|
155
|
+
|
156
|
+
case op
|
157
|
+
when :union
|
158
|
+
Zermelo.redis.sinterstore(r_dest_set, *r_source_keys)
|
159
|
+
Zermelo.redis.sunionstore(r_dest_set, r_source_key, r_dest_set)
|
160
|
+
when :intersect
|
161
|
+
Zermelo.redis.sinterstore(r_dest_set, r_source_key, *r_source_keys)
|
162
|
+
when :diff
|
163
|
+
Zermelo.redis.sinterstore(r_dest_set, *r_source_keys)
|
164
|
+
Zermelo.redis.sdiffstore(r_dest_set, r_source_key, r_dest_set)
|
165
|
+
end
|
166
|
+
|
167
|
+
return dest_set if shortcut.nil?
|
168
|
+
REDIS_SHORTCUTS[shortcut].call(*([r_dest_set] + opts[:shortcut_args]))
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -11,6 +11,91 @@ module Zermelo
|
|
11
11
|
def self.returns_type
|
12
12
|
:list
|
13
13
|
end
|
14
|
+
|
15
|
+
def resolve(backend, associated_class, opts = {})
|
16
|
+
case backend
|
17
|
+
when Zermelo::Backends::RedisBackend
|
18
|
+
source = opts[:source]
|
19
|
+
idx_attrs = opts[:index_attrs]
|
20
|
+
attr_types = opts[:attr_types]
|
21
|
+
temp_keys = opts[:temp_keys]
|
22
|
+
|
23
|
+
dest_list = associated_class.send(:temp_key, :list)
|
24
|
+
temp_keys << dest_list
|
25
|
+
r_dest_list = backend.key_to_redis_key(dest_list)
|
26
|
+
|
27
|
+
# TODO raise error in step construction if keys not
|
28
|
+
# passed as expected below
|
29
|
+
sort_attrs_and_orders = case options[:keys]
|
30
|
+
when String, Symbol
|
31
|
+
{options[:keys].to_s => options[:desc].is_a?(TrueClass) ? :desc : :asc}
|
32
|
+
when Array
|
33
|
+
options[:keys].each_with_object({}) do |k, memo|
|
34
|
+
memo[k.to_sym] = (options[:desc].is_a?(TrueClass) ? :desc : :asc)
|
35
|
+
end
|
36
|
+
when Hash
|
37
|
+
options[:keys]
|
38
|
+
end
|
39
|
+
|
40
|
+
# TODO check if complex attribute types or associations
|
41
|
+
# can be used for sorting
|
42
|
+
|
43
|
+
r_source = backend.key_to_redis_key(source)
|
44
|
+
|
45
|
+
# this set will be overwritten by the result list
|
46
|
+
case source.type
|
47
|
+
when :set
|
48
|
+
Zermelo.redis.sunionstore(r_dest_list, r_source)
|
49
|
+
when :sorted_set
|
50
|
+
Zermelo.redis.zunionstore(r_dest_list, [r_source])
|
51
|
+
end
|
52
|
+
|
53
|
+
class_key = associated_class.send(:class_key)
|
54
|
+
|
55
|
+
sort_attrs_and_orders.keys.reverse.each_with_index do |sort_attr, idx|
|
56
|
+
|
57
|
+
order = sort_attrs_and_orders[sort_attr]
|
58
|
+
|
59
|
+
sort_opts = {}
|
60
|
+
|
61
|
+
unless 'id'.eql?(sort_attr.to_s)
|
62
|
+
sort_opts.update(:by => "#{class_key}:*:attrs->#{sort_attr}")
|
63
|
+
end
|
64
|
+
|
65
|
+
if (idx + 1) == sort_attrs_and_orders.size
|
66
|
+
# only apply offset & limit on the last sort
|
67
|
+
o = options[:offset]
|
68
|
+
l = options[:limit]
|
69
|
+
|
70
|
+
if !(l.nil? && o.nil?)
|
71
|
+
o = o.nil? ? 0 : o.to_i
|
72
|
+
l = (l.nil? || (l.to_i < 1)) ? (Zermelo.redis.llen(dest_list) - o) : l
|
73
|
+
sort_opts.update(:limit => [o, l])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
order_parts = []
|
78
|
+
sort_attr_type = attr_types[sort_attr.to_sym]
|
79
|
+
unless [:integer, :float, :timestamp].include?(sort_attr_type)
|
80
|
+
order_parts << 'alpha'
|
81
|
+
end
|
82
|
+
order_parts << 'desc' if 'desc'.eql?(order.to_s)
|
83
|
+
|
84
|
+
unless order_parts.empty?
|
85
|
+
sort_opts.update(:order => order_parts.join(' '))
|
86
|
+
end
|
87
|
+
|
88
|
+
sort_opts.update(:store => r_dest_list)
|
89
|
+
Zermelo.redis.sort(r_dest_list, sort_opts)
|
90
|
+
end
|
91
|
+
|
92
|
+
shortcut = opts[:shortcut]
|
93
|
+
|
94
|
+
return dest_list if shortcut.nil?
|
95
|
+
Zermelo::Filters::Steps::ListStep::REDIS_SHORTCUTS[shortcut].
|
96
|
+
call(*([r_dest_list] + opts[:shortcut_args]))
|
97
|
+
end
|
98
|
+
end
|
14
99
|
end
|
15
100
|
end
|
16
101
|
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'zermelo/filters/steps/base_step'
|
2
|
+
|
3
|
+
module Zermelo
|
4
|
+
module Filters
|
5
|
+
class Steps
|
6
|
+
class SortedSetStep < Zermelo::Filters::Steps::BaseStep
|
7
|
+
def self.accepted_types
|
8
|
+
[:sorted_set]
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.returns_type
|
12
|
+
:sorted_set
|
13
|
+
end
|
14
|
+
|
15
|
+
REDIS_SHORTCUTS = {
|
16
|
+
:ids => proc {|key| Zermelo.redis.zrange(key, 0, -1) },
|
17
|
+
:count => proc {|key| Zermelo.redis.zcard(key) },
|
18
|
+
:exists? => proc {|key, id| !Zermelo.redis.zscore(key, id).nil? },
|
19
|
+
:first => proc {|key| Zermelo.redis.zrange(key, 0, 0).first },
|
20
|
+
:last => proc {|key| Zermelo.redis.zrevrange(key, 0, 0).first }
|
21
|
+
}
|
22
|
+
|
23
|
+
def resolve(backend, associated_class, opts = {})
|
24
|
+
op = @options[:op]
|
25
|
+
start = @options[:start]
|
26
|
+
finish = @options[:finish]
|
27
|
+
|
28
|
+
case backend
|
29
|
+
when Zermelo::Backends::RedisBackend
|
30
|
+
source = opts[:source]
|
31
|
+
idx_attrs = opts[:index_attrs]
|
32
|
+
attr_types = opts[:attr_types]
|
33
|
+
temp_keys = opts[:temp_keys]
|
34
|
+
|
35
|
+
range_temp_key = associated_class.send(:temp_key, :sorted_set)
|
36
|
+
temp_keys << range_temp_key
|
37
|
+
range_ids_set = backend.key_to_redis_key(range_temp_key)
|
38
|
+
|
39
|
+
if @options[:by_score]
|
40
|
+
start = '-inf' if start.nil? || (start <= 0)
|
41
|
+
finish = '+inf' if finish.nil? || (finish <= 0)
|
42
|
+
else
|
43
|
+
start = 0 if start.nil?
|
44
|
+
finish = -1 if finish.nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
args = [start, finish]
|
48
|
+
|
49
|
+
if @options[:by_score]
|
50
|
+
query = :zrangebyscore
|
51
|
+
args = args.map(&:to_s)
|
52
|
+
else
|
53
|
+
query = :zrange
|
54
|
+
end
|
55
|
+
|
56
|
+
args << {:with_scores => :true}
|
57
|
+
|
58
|
+
if @options[:limit]
|
59
|
+
args.last.update(:limit => [0, @options[:limit].to_i])
|
60
|
+
end
|
61
|
+
|
62
|
+
r_source = backend.key_to_redis_key(source)
|
63
|
+
args.unshift(r_source)
|
64
|
+
|
65
|
+
range_ids_scores = Zermelo.redis.send(query, *args)
|
66
|
+
|
67
|
+
unless range_ids_scores.empty?
|
68
|
+
Zermelo.redis.zadd(range_ids_set, range_ids_scores.map(&:reverse))
|
69
|
+
end
|
70
|
+
|
71
|
+
self.class.evaluate(backend, @options[:op], associated_class,
|
72
|
+
source, [range_temp_key], temp_keys, opts)
|
73
|
+
|
74
|
+
when Zermelo::Backends::InfluxDBBackend
|
75
|
+
|
76
|
+
query = ''
|
77
|
+
|
78
|
+
unless opts[:first].is_a?(TrueClass)
|
79
|
+
case @options[:op]
|
80
|
+
when :intersect_range, :diff_range
|
81
|
+
query += ' AND '
|
82
|
+
when :union_range
|
83
|
+
query += ' OR '
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
start = nil if !start.nil? && (start <= 0)
|
88
|
+
finish = nil if !finish.nil? && (finish <= 0)
|
89
|
+
|
90
|
+
unless start.nil? && finish.nil?
|
91
|
+
time_q = []
|
92
|
+
|
93
|
+
case @options[:op]
|
94
|
+
when :intersect_range, :union_range
|
95
|
+
unless start.nil?
|
96
|
+
time_q << "(time > #{start - 1}s)"
|
97
|
+
end
|
98
|
+
unless finish.nil?
|
99
|
+
time_q << "(time < #{finish}s)"
|
100
|
+
end
|
101
|
+
when :diff_range
|
102
|
+
unless start.nil?
|
103
|
+
time_q << "(time < #{start}s)"
|
104
|
+
end
|
105
|
+
unless finish.nil?
|
106
|
+
time_q << "(time > #{finish - 1}s)"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
query += time_q.join(' AND ')
|
111
|
+
end
|
112
|
+
|
113
|
+
query += ")"
|
114
|
+
query
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.evaluate(backend, op, associated_class, source, source_keys, temp_keys, opts = {})
|
119
|
+
shortcut = opts[:shortcut]
|
120
|
+
|
121
|
+
weights = case op
|
122
|
+
when :union, :union_range
|
123
|
+
[0.0] * source_keys.length
|
124
|
+
when :diff, :diff_range
|
125
|
+
[-1.0] * source_keys.length
|
126
|
+
end
|
127
|
+
|
128
|
+
r_source = backend.key_to_redis_key(source)
|
129
|
+
r_source_keys = source_keys.collect {|sk| backend.key_to_redis_key(sk) }
|
130
|
+
|
131
|
+
dest_sorted_set = associated_class.send(:temp_key, :sorted_set)
|
132
|
+
temp_keys << dest_sorted_set
|
133
|
+
r_dest_sorted_set = backend.key_to_redis_key(dest_sorted_set)
|
134
|
+
|
135
|
+
case op
|
136
|
+
when :union, :union_range
|
137
|
+
Zermelo.redis.zinterstore(r_dest_sorted_set, r_source_keys, :weights => weights, :aggregate => 'max')
|
138
|
+
Zermelo.redis.zunionstore(r_dest_sorted_set, [r_source, r_dest_sorted_set])
|
139
|
+
when :intersect, :intersect_range
|
140
|
+
Zermelo.redis.zinterstore(r_dest_sorted_set, [r_source] + r_source_keys, :weights => weights, :aggregate => 'max')
|
141
|
+
when :diff, :diff_range
|
142
|
+
# 'zdiffstore' via weights, relies on non-zero scores being used
|
143
|
+
# see https://code.google.com/p/redis/issues/detail?id=579
|
144
|
+
Zermelo.redis.zinterstore(r_dest_sorted_set, r_source_keys, :weights => weights, :aggregate => 'max')
|
145
|
+
Zermelo.redis.zunionstore(r_dest_sorted_set, [r_source, r_dest_sorted_set])
|
146
|
+
Zermelo.redis.zremrangebyscore(r_dest_sorted_set, "0", "0")
|
147
|
+
end
|
148
|
+
|
149
|
+
return dest_sorted_set if shortcut.nil?
|
150
|
+
REDIS_SHORTCUTS[shortcut].call(*([r_dest_sorted_set] + opts[:shortcut_args]))
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -102,13 +102,25 @@ module Zermelo
|
|
102
102
|
|
103
103
|
private
|
104
104
|
|
105
|
+
def class_key
|
106
|
+
self.name.demodulize.underscore
|
107
|
+
end
|
108
|
+
|
105
109
|
def ids_key
|
106
|
-
@ids_key ||= Zermelo::Records::Key.new(
|
107
|
-
|
110
|
+
@ids_key ||= Zermelo::Records::Key.new(
|
111
|
+
:klass => self, :name => 'ids',
|
112
|
+
:type => :set,
|
113
|
+
:object => :attribute
|
114
|
+
)
|
108
115
|
end
|
109
116
|
|
110
|
-
def
|
111
|
-
|
117
|
+
def temp_key(type)
|
118
|
+
Zermelo::Records::Key.new(
|
119
|
+
:klass => self,
|
120
|
+
:name => SecureRandom.hex(16),
|
121
|
+
:type => type,
|
122
|
+
:object => :temporary
|
123
|
+
)
|
112
124
|
end
|
113
125
|
|
114
126
|
def load(id)
|
@@ -51,7 +51,7 @@ module Zermelo
|
|
51
51
|
attr_types = self.class.attribute_types.reject {|k, v| k == :id}
|
52
52
|
|
53
53
|
attrs_to_load = attr_types.collect do |name, type|
|
54
|
-
Zermelo::Records::Key.new(:klass =>
|
54
|
+
Zermelo::Records::Key.new(:klass => self.class,
|
55
55
|
:id => self.id, :name => name, :type => type, :object => :attribute)
|
56
56
|
end
|
57
57
|
|
@@ -167,12 +167,12 @@ module Zermelo
|
|
167
167
|
end
|
168
168
|
|
169
169
|
self.class.attribute_types.each_pair {|name, type|
|
170
|
-
key = Zermelo::Records::Key.new(:klass => self.class
|
170
|
+
key = Zermelo::Records::Key.new(:klass => self.class,
|
171
171
|
:id => self.id, :name => name.to_s, :type => type, :object => :attribute)
|
172
172
|
backend.clear(key)
|
173
173
|
}
|
174
174
|
|
175
|
-
record_key = Zermelo::Records::Key.new(:klass => self.class
|
175
|
+
record_key = Zermelo::Records::Key.new(:klass => self.class,
|
176
176
|
:id => self.id)
|
177
177
|
backend.purge(record_key)
|
178
178
|
end
|
@@ -190,7 +190,7 @@ module Zermelo
|
|
190
190
|
@attribute_keys ||= self.class.attribute_types.reject {|k, v|
|
191
191
|
k == :id
|
192
192
|
}.inject({}) {|memo, (name, type)|
|
193
|
-
memo[name.to_s] = Zermelo::Records::Key.new(:klass => self.class
|
193
|
+
memo[name.to_s] = Zermelo::Records::Key.new(:klass => self.class,
|
194
194
|
:id => self.id, :name => name.to_s, :type => type, :object => :attribute)
|
195
195
|
memo
|
196
196
|
}
|
data/lib/zermelo/records/key.rb
CHANGED
data/lib/zermelo/version.rb
CHANGED
data/lib/zermelo.rb
CHANGED
@@ -95,7 +95,15 @@ module Zermelo
|
|
95
95
|
debug_str
|
96
96
|
}
|
97
97
|
end
|
98
|
-
@proxied_connection.send(name, *args, &block)
|
98
|
+
result = @proxied_connection.send(name, *args, &block)
|
99
|
+
unless Zermelo.logger.nil?
|
100
|
+
Zermelo.logger.debug {
|
101
|
+
debug_str = "#{name}"
|
102
|
+
debug_str += " result: #{result}"
|
103
|
+
debug_str
|
104
|
+
}
|
105
|
+
end
|
106
|
+
result
|
99
107
|
end
|
100
108
|
end
|
101
109
|
|