zermelo 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|