zermelo 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 69911858d3394494076bade1249037f111eb5e7b
4
- data.tar.gz: 5b2c9e463d7fb0b71a7135bad76b481e4e18629a
3
+ metadata.gz: 41344d467203608ea5d05ba4e7e50ba3d0ba08c5
4
+ data.tar.gz: 62498b43b9556a7de290d83fc118ca0aa8ed6c48
5
5
  SHA512:
6
- metadata.gz: b2b62aabc2f4421d99e53bc298e260550d2124cb957786c6ef1bce894cb0fd43c0cd704a6378e6a6acfbc2cfebffda52412984756fc314f98322a2ea63cb7a23
7
- data.tar.gz: 69d7a165a1da92e759c6923828d12340d793eead6ee20681a0e22c9f7dde901b0421323ce0fd4c960bc708f5d84e9ebfab79bf166f638a3768032c8b75214074
6
+ metadata.gz: 475b586c7cca398659befa76233ff27eda95ead07db02b7ac56c3fdd8fbb4ef6ea724708da35ca9d3e471fa4f54023ea18129f145ec141053d6ea7bf601ee010
7
+ data.tar.gz: d3b7c8da76210b3d6f0c350bbc3601ec4d3f78c336864a1d885e5a9ac1682db0bd8575a16d68641869eb791a3799ee5e5ed92fdaeca7d0c936ccdc8df23c057c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## Zermelo Changelog
2
2
 
3
+ # 1.4.0 - 2015-10-07
4
+
5
+ * store sorted_set ids in zset, makes some queries combine properly that
6
+ previously resulted in errors
7
+ * bugfix transactions, weren't applied properly
8
+
3
9
  # 1.3.0 - 2015-08-15
4
10
 
5
11
  * handle some Zermelo objects as query values, less data back-and-forth
@@ -114,7 +114,7 @@ module Zermelo
114
114
  idx_data = name.nil? ? @index_data : @index_data[name]
115
115
  yield idx_data unless idx_data.nil?
116
116
  end
117
- end
117
+ end
118
118
  # end used internally within Zermelo
119
119
 
120
120
  def add_index_data(klass, name, args = {})
@@ -82,7 +82,7 @@ module Zermelo
82
82
  def add_ids(*record_ids)
83
83
  raise 'No record ids to add' if record_ids.empty?
84
84
  @parent_klass.lock(*@lock_klasses) do
85
- records = @associated_class.find_by_ids!(*record_ids)
85
+ @associated_class.find_by_ids!(*record_ids) # ensure they exist
86
86
  _add_ids({:callbacks => true}, *record_ids)
87
87
  end
88
88
  end
@@ -155,20 +155,23 @@ module Zermelo
155
155
  when :has_many
156
156
  # inverse is belongs_to
157
157
  record_ids.each do |record_id|
158
- _inverse.id = record_id
159
- @backend.add(_inverse, "#{@inverse}_id" => @parent_id)
158
+ _inverse_copy = _inverse.clone
159
+ _inverse_copy.id = record_id
160
+ @backend.add(_inverse_copy, "#{@inverse}_id" => @parent_id)
160
161
  end
161
162
  when :has_sorted_set
162
163
  # inverse is belongs_to
163
- record_ids.each do |(score, record_id)|
164
- _inverse.id = record_id
165
- @backend.add(_inverse, "#{@inverse}_id" => @parent_id)
164
+ record_ids.each do |score_and_record_id|
165
+ _inverse_copy = _inverse.clone
166
+ _inverse_copy.id = score_and_record_id.last
167
+ @backend.add(_inverse_copy, "#{@inverse}_id" => @parent_id)
166
168
  end
167
169
  when :has_and_belongs_to_many
168
170
  # inverse is has_and_belongs_to_many
169
171
  record_ids.each do |record_id|
170
- _inverse.id = record_id
171
- @backend.add(_inverse, @parent_id)
172
+ _inverse_copy = _inverse.clone
173
+ _inverse_copy.id = record_id
174
+ @backend.add(_inverse_copy, @parent_id)
172
175
  end
173
176
  end
174
177
 
@@ -194,14 +197,16 @@ module Zermelo
194
197
  when :has_many, :has_sorted_set
195
198
  # inverse is belongs_to
196
199
  record_ids.each do |record_id|
197
- _inverse.id = record_id
198
- @backend.delete(_inverse, "#{@inverse}_id")
200
+ _inverse_copy = _inverse.clone
201
+ _inverse_copy.id = record_id
202
+ @backend.delete(_inverse_copy, "#{@inverse}_id")
199
203
  end
200
204
  when :has_and_belongs_to_many
201
205
  # inverse is has_and_belongs_to_many
202
206
  record_ids.each do |record_id|
203
- _inverse.id = record_id
204
- @backend.delete(_inverse, @parent_id)
207
+ _inverse_copy = _inverse.clone
208
+ _inverse_copy.id = record_id
209
+ @backend.delete(_inverse_copy, @parent_id)
205
210
  end
206
211
  end
207
212
 
@@ -12,6 +12,11 @@ module Zermelo
12
12
 
13
13
  include Zermelo::Backend
14
14
 
15
+ def initialize
16
+ @transaction_redis = nil
17
+ @changes = nil
18
+ end
19
+
15
20
  # def default_sorted_set_key
16
21
  # :timestamp
17
22
  # end
@@ -153,9 +158,9 @@ module Zermelo
153
158
  end
154
159
  end
155
160
 
156
- # TODO converge usage of idx_class and _index lookup invocation
161
+ def index_lookup(att, associated_class, type, idx_class, value,
162
+ attr_type, temp_keys)
157
163
 
158
- def index_lookup(att, associated_class, idx_class, value, attr_type, temp_keys)
159
164
  if (idx_class == Zermelo::Associations::RangeIndex) && !value.is_a?(Zermelo::Filters::IndexRange)
160
165
  raise "Range index must be passed a range"
161
166
  end
@@ -164,7 +169,7 @@ module Zermelo
164
169
  when Regexp
165
170
  raise "Can't query non-string values via regexp" unless :string.eql?(attr_type)
166
171
 
167
- idx_key = associated_class.send(:temp_key, :set)
172
+ idx_key = associated_class.send(:temp_key, type)
168
173
  temp_keys << idx_key
169
174
  idx_result = key_to_redis_key(idx_key)
170
175
 
@@ -182,7 +187,15 @@ module Zermelo
182
187
  (starts_with_string_re === k) &&
183
188
  (value === unescape_key_name(k.sub(starts_with_string_re, '')))
184
189
  })
185
- Zermelo.redis.sadd(idx_result, matching_ids) unless matching_ids.empty?
190
+
191
+ unless matching_ids.empty?
192
+ case type
193
+ when :set
194
+ Zermelo.redis.sadd(idx_result, matching_ids)
195
+ when :sorted_set
196
+ Zermelo.redis.zadd(idx_result, matching_ids.map {|m| [1, m]})
197
+ end
198
+ end
186
199
  when 'Zermelo::Associations::Index'
187
200
  key_root = key_to_redis_key(Zermelo::Records::Key.new(
188
201
  :klass => associated_class,
@@ -209,7 +222,14 @@ module Zermelo
209
222
  value === $1
210
223
  end
211
224
 
212
- Zermelo.redis.sunionstore(idx_result, matching_sets) unless matching_sets.empty?
225
+ unless matching_sets.empty?
226
+ case type
227
+ when :set
228
+ Zermelo.redis.sunionstore(idx_result, matching_sets)
229
+ when :sorted_set
230
+ Zermelo.redis.zunionstore(idx_result, matching_sets)
231
+ end
232
+ end
213
233
  end
214
234
  idx_key
215
235
  else
@@ -217,30 +237,20 @@ module Zermelo
217
237
 
218
238
  case index
219
239
  when Zermelo::Associations::RangeIndex
220
- r_index_key = key_to_redis_key(index.key)
221
- range = if value.by_score
222
- range_start = value.start.nil? ? '-inf' : safe_value(attr_type, value.start)
223
- range_finish = value.finish.nil? ? '+inf' : safe_value(attr_type, value.finish)
224
- Zermelo.redis.zrangebyscore(r_index_key, range_start, range_finish)
225
- else
226
- range_start = value.start || 0
227
- range_finish = value.finish || -1
228
- Zermelo.redis.zrange(r_index_key, range_start, range_finish)
229
- end
230
-
231
- # TODO another way for index_lookup to indicate 'empty result', rather
232
- # than creating & returning an empty key
233
- idx_key = associated_class.send(:temp_key, :set)
234
- temp_keys << idx_key
235
- Zermelo.redis.sadd(key_to_redis_key(idx_key), range) unless range.empty?
236
- idx_key
240
+ range_lookup(index.key, value, type, attr_type, associated_class, temp_keys)
237
241
  when Zermelo::Associations::UniqueIndex
238
- idx_key = associated_class.send(:temp_key, :set)
242
+ idx_key = associated_class.send(:temp_key, type)
239
243
  temp_keys << idx_key
240
244
 
241
- Zermelo.redis.sadd(key_to_redis_key(idx_key),
242
- Zermelo.redis.hget(key_to_redis_key(index.key),
243
- index_keys(attr_type, value).join(':')))
245
+ val = Zermelo.redis.hget(key_to_redis_key(index.key),
246
+ index_keys(attr_type, value).join(':'))
247
+
248
+ case type
249
+ when :set
250
+ Zermelo.redis.sadd(key_to_redis_key(idx_key), val)
251
+ when :sorted_set
252
+ Zermelo.redis.zadd(key_to_redis_key(idx_key), [1, val])
253
+ end
244
254
  idx_key
245
255
  when Zermelo::Associations::Index
246
256
  index.key(value)
@@ -248,15 +258,49 @@ module Zermelo
248
258
  end
249
259
  end
250
260
 
261
+ def range_lookup(key, range, type, attr_type, associated_class, temp_keys)
262
+ r_key = key_to_redis_key(key)
263
+ opts = case type
264
+ when :set
265
+ {}
266
+ when :sorted_set
267
+ {:with_scores => true}
268
+ end
269
+ result = if range.by_score
270
+ range_start = range.start.nil? ? '-inf' : safe_value(attr_type, range.start)
271
+ range_finish = range.finish.nil? ? '+inf' : safe_value(attr_type, range.finish)
272
+ Zermelo.redis.zrangebyscore(r_key, range_start, range_finish, opts)
273
+ else
274
+ range_start = range.start || 0
275
+ range_finish = range.finish || -1
276
+ Zermelo.redis.zrange(r_key, range_start, range_finish, opts)
277
+ end
278
+
279
+ # TODO another way for index_lookup to indicate 'empty result', rather
280
+ # than creating & returning an empty key
281
+ ret_key = associated_class.send(:temp_key, key.type)
282
+ temp_keys << ret_key
283
+ unless result.empty?
284
+ r_key = key_to_redis_key(ret_key)
285
+ case type
286
+ when :set
287
+ Zermelo.redis.sadd(r_key, result)
288
+ when :sorted_set
289
+ Zermelo.redis.zadd(r_key, result.map {|r| [r.last, r.first]})
290
+ end
291
+ end
292
+ ret_key
293
+ end
294
+
251
295
  private
252
296
 
253
297
  def change(op, key, value = nil, key_to = nil, value_to = nil)
254
298
  ch = [op, key, value, key_to, value_to]
255
- if @in_transaction
256
- @changes << ch
257
- else
299
+ if @transaction_redis.nil?
258
300
  apply_changes([ch])
301
+ return
259
302
  end
303
+ @changes << ch
260
304
  end
261
305
 
262
306
  def apply_changes(changes)
@@ -169,8 +169,8 @@ module Zermelo
169
169
  end
170
170
 
171
171
  def associations_for(name)
172
- data_type, type_klass = @associated_class.send(:with_association_data, name.to_sym) do |data|
173
- [data.data_type, data.type_klass]
172
+ data_type = @associated_class.send(:with_association_data, name.to_sym) do |data|
173
+ data.data_type
174
174
  end
175
175
 
176
176
  lock {
@@ -25,8 +25,8 @@ module Zermelo
25
25
  when Zermelo::Backends::Redis
26
26
 
27
27
  source = opts[:source]
28
- idx_attrs = opts[:index_attrs]
29
- attr_types = opts[:attr_types]
28
+ # idx_attrs = opts[:index_attrs]
29
+ # attr_types = opts[:attr_types]
30
30
  temp_keys = opts[:temp_keys]
31
31
 
32
32
  # TODO apply these transformations via a subset?
@@ -46,7 +46,7 @@ module Zermelo
46
46
  r_source, o, (o + l), :with_scores => true
47
47
  )
48
48
 
49
- Zermelo.redis.zadd(r_limited, lim.collect {|l| [l[1], l[0]]} )
49
+ Zermelo.redis.zadd(r_limited, lim.collect {|li| [li[1], li[0]]} )
50
50
 
51
51
  [limited, r_limited]
52
52
  when :list
@@ -26,9 +26,14 @@ module Zermelo
26
26
 
27
27
  source_keys = @attributes.each_with_object([]) do |(att, value), memo|
28
28
  idx_class = nil
29
+ use_sort_attr = false
29
30
  unless :id.eql?(att)
30
31
  idx_class = idx_attrs[att.to_s]
31
- raise "'#{att}' property is not indexed" if idx_class.nil?
32
+ if idx_class.nil?
33
+ use_sort_attr = :sorted_set.eql?(source.type) &&
34
+ att.eql?(associated_class.instance_variable_get('@sort_attribute'))
35
+ raise "'#{att}' property is not indexed" unless use_sort_attr
36
+ end
32
37
  end
33
38
 
34
39
  if [Set, Array].any? {|t| value.is_a?(t) }
@@ -37,7 +42,21 @@ module Zermelo
37
42
  r_conditions_set = backend.key_to_redis_key(conditions_set)
38
43
 
39
44
  backend.temp_key_wrap do |conditions_temp_keys|
40
- if idx_class.nil?
45
+ if use_sort_attr
46
+ range_keys = value.collect {|v|
47
+ rl = backend.range_lookup(associated_class.ids_key, v,
48
+ source_type, attr_types[att], associated_class, conditions_temp_keys)
49
+ backend.key_to_redis_key(rl)
50
+ }
51
+
52
+ case source.type
53
+ when :set
54
+ Zermelo.redis.sunionstore(r_conditions_set, *range_keys)
55
+ when :sorted_set
56
+ Zermelo.redis.zunionstore(r_conditions_set, range_keys)
57
+ end
58
+ elsif idx_class.nil?
59
+ # query against the :id field
41
60
  cond_objects, cond_ids = value.partition do |v|
42
61
  [Zermelo::Filter, Zermelo::Associations::Multiple].any? {|c| v.is_a?(c)}
43
62
  end
@@ -53,15 +72,33 @@ module Zermelo
53
72
  backend.key_to_redis_key(k)
54
73
  end
55
74
 
56
- Zermelo.redis.sunionstore(r_conditions_set, *cond_keys)
75
+ case source.type
76
+ when :set
77
+ Zermelo.redis.sunionstore(r_conditions_set, *cond_keys)
78
+ when :sorted_set
79
+ Zermelo.redis.zunionstore(r_conditions_set, cond_keys)
80
+ end
57
81
  end
58
82
  unless cond_ids.empty?
59
- cond_ids.map! {|ci| ci.is_a?(Zermelo::Associations::Singular) ? ci.id : ci }
60
- Zermelo.redis.sadd(r_conditions_set, cond_ids)
83
+ case source.type
84
+ when :set
85
+ s_ids = cond_ids.map {|ci| ci.is_a?(Zermelo::Associations::Singular) ? ci.id : ci }
86
+ Zermelo.redis.sadd(r_conditions_set, s_ids)
87
+ when :sorted_set
88
+ z_ids = cond_ids.map do |ci|
89
+ # is 1 a valid sort value? what's happening with it?
90
+ if ci.is_a?(Zermelo::Associations::Singular)
91
+ [1, ci.id]
92
+ else
93
+ [1, ci]
94
+ end
95
+ end
96
+ Zermelo.redis.zadd(r_conditions_set, z_ids)
97
+ end
61
98
  end
62
99
  else
63
- index_keys = value.to_a.collect {|v|
64
- il = backend.index_lookup(att, associated_class,
100
+ index_keys = value.collect {|v|
101
+ il = backend.index_lookup(att, associated_class, source.type,
65
102
  idx_class, v, attr_types[att], conditions_temp_keys)
66
103
  backend.key_to_redis_key(il)
67
104
  }
@@ -75,6 +112,9 @@ module Zermelo
75
112
  end
76
113
  end
77
114
  memo << conditions_set
115
+ elsif use_sort_attr
116
+ memo << backend.range_lookup(associated_class.ids_key, value,
117
+ source.type, attr_types[att], associated_class, temp_keys)
78
118
  elsif idx_class.nil?
79
119
  case value
80
120
  when Zermelo::Filter
@@ -84,15 +124,22 @@ module Zermelo
84
124
  when Zermelo::Associations::Multiple
85
125
  memo << value.instance_variable_get('@record_ids_key')
86
126
  else
87
- ts = associated_class.send(:temp_key, :set)
127
+ ts = associated_class.send(:temp_key, source.type)
88
128
  temp_keys << ts
89
129
  r_ts = backend.key_to_redis_key(ts)
90
- Zermelo.redis.sadd(r_ts,
91
- value.is_a?(Zermelo::Associations::Singular) ? value.id : value)
130
+ case source.type
131
+ when :set
132
+ s_id = value.is_a?(Zermelo::Associations::Singular) ? value.id : value
133
+ Zermelo.redis.sadd(r_ts, s_id)
134
+ when :sorted_set
135
+ # is 1 a valid sort value? what's happening with it?
136
+ z_id = [1, (value.is_a?(Zermelo::Associations::Singular) ? value.id : value)]
137
+ Zermelo.redis.zadd(r_ts, z_id)
138
+ end
92
139
  memo << ts
93
140
  end
94
141
  else
95
- memo << backend.index_lookup(att, associated_class,
142
+ memo << backend.index_lookup(att, associated_class, source.type,
96
143
  idx_class, value, attr_types[att], temp_keys)
97
144
  end
98
145
  end
@@ -16,7 +16,7 @@ module Zermelo
16
16
  case backend
17
17
  when Zermelo::Backends::Redis
18
18
  source = opts[:source]
19
- idx_attrs = opts[:index_attrs]
19
+ # idx_attrs = opts[:index_attrs]
20
20
  attr_types = opts[:attr_types]
21
21
  temp_keys = opts[:temp_keys]
22
22
 
@@ -12,9 +12,7 @@ require 'zermelo/records/class_methods'
12
12
  require 'zermelo/records/type_validator'
13
13
 
14
14
  module Zermelo
15
-
16
15
  module Record
17
-
18
16
  extend ActiveSupport::Concern
19
17
 
20
18
  include Zermelo::Records::InstMethods
@@ -31,11 +29,11 @@ module Zermelo
31
29
 
32
30
  # include ActiveModel::MassAssignmentSecurity
33
31
 
34
- @lock = Monitor.new
35
-
36
32
  extend Zermelo::Records::ClassMethods
37
33
  extend Zermelo::Associations::ClassMethods
38
34
 
35
+ @lock = Monitor.new
36
+
39
37
  attr_accessor :attributes
40
38
 
41
39
  define_model_callbacks :create, :update, :destroy
@@ -47,7 +45,5 @@ module Zermelo
47
45
 
48
46
  define_attributes :id => :string
49
47
  end
50
-
51
48
  end
52
-
53
49
  end
@@ -11,11 +11,8 @@ require 'zermelo/records/attributes'
11
11
  require 'zermelo/records/key'
12
12
 
13
13
  module Zermelo
14
-
15
14
  module Records
16
-
17
15
  module ClassMethods
18
-
19
16
  include Zermelo::Records::Attributes
20
17
 
21
18
  extend Forwardable
@@ -37,14 +34,6 @@ module Zermelo
37
34
  "%08x-%04x-%04x-%04x-%04x%08x" % ary
38
35
  end
39
36
 
40
- def add_id(id)
41
- backend.add(ids_key, id.to_s)
42
- end
43
-
44
- def delete_id(id)
45
- backend.delete(ids_key, id.to_s)
46
- end
47
-
48
37
  def lock(*klasses, &block)
49
38
  klasses += [self] unless klasses.include?(self)
50
39
  backend.lock(*klasses, &block)
@@ -57,7 +46,7 @@ module Zermelo
57
46
 
58
47
  begin
59
48
  yield
60
- rescue Exception => e
49
+ rescue Exception # => e
61
50
  backend.abort_transaction
62
51
  # p e.message
63
52
  # puts e.backtrace.join("\n")
@@ -94,14 +83,6 @@ module Zermelo
94
83
  self.name.demodulize.underscore
95
84
  end
96
85
 
97
- def ids_key
98
- @ids_key ||= Zermelo::Records::Key.new(
99
- :klass => self, :name => 'ids',
100
- :type => :set,
101
- :object => :attribute
102
- )
103
- end
104
-
105
86
  def temp_key(type)
106
87
  Zermelo::Records::Key.new(
107
88
  :klass => self,
@@ -119,9 +100,60 @@ module Zermelo
119
100
  def filter
120
101
  backend.filter(ids_key, self)
121
102
  end
103
+ end
104
+
105
+ module Unordered
106
+ extend ActiveSupport::Concern
107
+
108
+ module ClassMethods
109
+ def ids_key
110
+ @ids_key ||= Zermelo::Records::Key.new(
111
+ :klass => self, :name => 'ids',
112
+ :type => :set,
113
+ :object => :attribute
114
+ )
115
+ end
116
+
117
+ def add_id(id)
118
+ backend.add(ids_key, id)
119
+ end
122
120
 
121
+ def delete_id(id)
122
+ backend.delete(ids_key, id)
123
+ end
124
+ end
123
125
  end
124
126
 
125
- end
127
+ module Ordered
128
+ extend ActiveSupport::Concern
129
+
130
+ module ClassMethods
131
+ extend Forwardable
126
132
 
133
+ def_delegators :filter,
134
+ :first, :last
135
+
136
+ def ids_key
137
+ @ids_key ||= Zermelo::Records::Key.new(
138
+ :klass => self, :name => 'ids',
139
+ :type => :sorted_set,
140
+ :object => :attribute
141
+ )
142
+ end
143
+
144
+ def define_sort_attribute(k)
145
+ @sort_attribute = k
146
+ @sort_attribute_type = attribute_types[k.to_sym]
147
+ end
148
+
149
+ def add_id(id, val)
150
+ backend.add(ids_key, [backend.safe_value(@sort_attribute_type, val), id])
151
+ end
152
+
153
+ def delete_id(id)
154
+ backend.delete(ids_key, id)
155
+ end
156
+ end
157
+ end
158
+ end
127
159
  end
@@ -25,6 +25,7 @@ module Zermelo
25
25
  extend ActiveSupport::Concern
26
26
 
27
27
  include Zermelo::Record
28
+ include Zermelo::Records::Unordered
28
29
 
29
30
  included do
30
31
  set_backend :influxdb
@@ -83,6 +83,15 @@ module Zermelo
83
83
  creating = !self.persisted?
84
84
  saved = false
85
85
 
86
+ sort_val = nil
87
+ case self
88
+ when Zermelo::Records::Ordered
89
+ sort_attr = self.class.instance_variable_get('@sort_attribute')
90
+ raise 'Ordered record types must define_sort_attribute' if sort_attr.nil?
91
+ sort_val = @attributes[sort_attr.to_s]
92
+ raise "Value required for sort_attribute #{sort_attr}" if sort_val.nil?
93
+ end
94
+
86
95
  run_callbacks( (creating ? :create : :update) ) do
87
96
 
88
97
  idx_attrs = self.class.send(:with_index_data) do |d|
@@ -119,9 +128,16 @@ module Zermelo
119
128
  end
120
129
  end
121
130
 
122
- # ids is a set, so update won't create duplicates
131
+ # ids is a set/sorted set, so update won't create duplicates
123
132
  # NB influxdb backend doesn't need this
124
- self.class.add_id(@attributes['id'])
133
+
134
+ # FIXME distinguish between this in the class methods?
135
+ case self
136
+ when Zermelo::Records::Ordered
137
+ self.class.add_id(@attributes['id'], sort_val)
138
+ when Zermelo::Records::Unordered
139
+ self.class.add_id(@attributes['id'])
140
+ end
125
141
  end
126
142
 
127
143
  @is_new = false
@@ -4,10 +4,22 @@ require 'zermelo/record'
4
4
 
5
5
  module Zermelo
6
6
  module Records
7
- module Redis
7
+ module RedisSet
8
8
  extend ActiveSupport::Concern
9
9
 
10
10
  include Zermelo::Record
11
+ include Zermelo::Records::Unordered
12
+
13
+ included do
14
+ set_backend :redis
15
+ end
16
+ end
17
+
18
+ module RedisSortedSet
19
+ extend ActiveSupport::Concern
20
+
21
+ include Zermelo::Record
22
+ include Zermelo::Records::Ordered
11
23
 
12
24
  included do
13
25
  set_backend :redis
@@ -8,9 +8,9 @@ module Zermelo
8
8
  value = record.send(name)
9
9
  next if value.nil?
10
10
  valid_type = Zermelo::ALL_TYPES[type]
11
- unless valid_type.any? {|type| value.is_a?(type) }
11
+ unless valid_type.any? {|t| value.is_a?(t) }
12
12
  count = (valid_type.size > 1) ? 'one of ' : ''
13
- type_str = valid_type.collect {|type| type.name }.join(", ")
13
+ type_str = valid_type.collect {|t| t.name }.join(", ")
14
14
  record.errors.add(name, "should be #{count}#{type_str} but is #{value.class.name}")
15
15
  end
16
16
  end
@@ -1,3 +1,3 @@
1
1
  module Zermelo
2
- VERSION = '1.3.0'
2
+ VERSION = '1.4.0'
3
3
  end
@@ -12,7 +12,7 @@ describe Zermelo::Associations::Index do
12
12
 
13
13
  module ZermeloExamples
14
14
  class RedisIndex
15
- include Zermelo::Records::Redis
15
+ include Zermelo::Records::RedisSet
16
16
  define_attributes :emotion => :string
17
17
  validates :emotion, :presence => true, :inclusion => {:in => %w(happy sad indifferent)}
18
18
  index_by :emotion
@@ -212,13 +212,13 @@ describe Zermelo::Associations::Multiple do
212
212
 
213
213
  module ZermeloExamples
214
214
  class AssociationsHasManyParentRedis
215
- include Zermelo::Records::Redis
215
+ include Zermelo::Records::RedisSet
216
216
  has_many :children, :class_name => 'ZermeloExamples::AssociationsHasManyChildRedis',
217
217
  :inverse_of => :parent
218
218
  end
219
219
 
220
220
  class AssociationsHasManyChildRedis
221
- include Zermelo::Records::Redis
221
+ include Zermelo::Records::RedisSet
222
222
  define_attributes :important => :boolean
223
223
  index_by :important
224
224
  belongs_to :parent, :class_name => 'ZermeloExamples::AssociationsHasManyParentRedis',
@@ -671,7 +671,7 @@ describe Zermelo::Associations::Multiple do
671
671
 
672
672
  module ZermeloExamples
673
673
  class AssociationsHasAndBelongsToManyPrimaryRedis
674
- include Zermelo::Records::Redis
674
+ include Zermelo::Records::RedisSet
675
675
  define_attributes :active => :boolean
676
676
  index_by :active
677
677
  has_and_belongs_to_many :secondaries,
@@ -680,7 +680,7 @@ describe Zermelo::Associations::Multiple do
680
680
  end
681
681
 
682
682
  class AssociationsHasAndBelongsToManySecondaryRedis
683
- include Zermelo::Records::Redis
683
+ include Zermelo::Records::RedisSet
684
684
  # define_attributes :important => :boolean
685
685
  # index_by :important
686
686
  has_and_belongs_to_many :primaries,
@@ -773,7 +773,7 @@ describe Zermelo::Associations::Multiple do
773
773
 
774
774
  module ZermeloExamples
775
775
  class AssociationsHasSortedSetParentRedis
776
- include Zermelo::Records::Redis
776
+ include Zermelo::Records::RedisSet
777
777
  has_sorted_set :children, :class_name => 'ZermeloExamples::AssociationsHasSortedSetChildRedis',
778
778
  :inverse_of => :parent, :key => :timestamp
779
779
  has_sorted_set :reversed_children, :class_name => 'ZermeloExamples::AssociationsHasSortedSetChildRedis',
@@ -781,11 +781,11 @@ describe Zermelo::Associations::Multiple do
781
781
  end
782
782
 
783
783
  class AssociationsHasSortedSetChildRedis
784
- include Zermelo::Records::Redis
784
+ include Zermelo::Records::RedisSortedSet
785
785
  define_attributes :emotion => :string,
786
786
  :timestamp => :timestamp
787
+ define_sort_attribute :timestamp
787
788
  index_by :emotion
788
- range_index_by :timestamp
789
789
  belongs_to :parent, :class_name => 'ZermeloExamples::AssociationsHasSortedSetParentRedis',
790
790
  :inverse_of => :children
791
791
  belongs_to :reversed_parent, :class_name => 'ZermeloExamples::AssociationsHasSortedSetParentRedis',
@@ -811,10 +811,9 @@ describe Zermelo::Associations::Multiple do
811
811
  'timestamp' => attrs[:timestamp].to_f}.to_a.flatten)
812
812
 
813
813
  redis.sadd("#{ck}::indices:by_emotion:string:#{attrs[:emotion]}", attrs[:id])
814
- redis.zadd("#{ck}::indices:by_timestamp", attrs[:timestamp].to_f, attrs[:id])
815
814
  redis.hmset("#{ck}:#{attrs[:id]}:assocs:belongs_to",
816
815
  {'parent_id' => parent.id}.to_a.flatten) unless parent.nil?
817
- redis.sadd("#{ck}::attrs:ids", attrs[:id])
816
+ redis.zadd("#{ck}::attrs:ids", attrs[:timestamp].to_f, attrs[:id])
818
817
  end
819
818
 
820
819
  def create_reversed_child(parent, attrs = {})
@@ -824,10 +823,9 @@ describe Zermelo::Associations::Multiple do
824
823
  'timestamp' => attrs[:timestamp].to_f}.to_a.flatten)
825
824
 
826
825
  redis.sadd("#{ck}::indices:by_emotion:string:#{attrs[:emotion]}", attrs[:id])
827
- redis.zadd("#{ck}::indices:by_timestamp", attrs[:timestamp].to_f, attrs[:id])
828
826
  redis.hmset("#{ck}:#{attrs[:id]}:assocs:belongs_to",
829
827
  {'reversed_parent_id' => parent.id}.to_a.flatten) unless parent.nil?
830
- redis.sadd("#{ck}::attrs:ids", attrs[:id])
828
+ redis.zadd("#{ck}::attrs:ids", attrs[:timestamp].to_f, attrs[:id])
831
829
  end
832
830
 
833
831
  let(:parent) {
@@ -846,11 +844,10 @@ describe Zermelo::Associations::Multiple do
846
844
  "#{pk}:8:assocs:children_ids",
847
845
  "#{ck}::attrs:ids",
848
846
  "#{ck}::indices:by_emotion:string:indifferent",
849
- "#{ck}::indices:by_timestamp",
850
847
  "#{ck}:4:attrs",
851
848
  "#{ck}:4:assocs:belongs_to"])
852
849
 
853
- expect(redis.smembers("#{ck}::attrs:ids")).to eq(['4'])
850
+ expect(redis.zrange("#{ck}::attrs:ids", 0, -1)).to eq(['4'])
854
851
  expect(redis.hgetall("#{ck}:4:attrs")).to eq(
855
852
  {'emotion' => 'indifferent', 'timestamp' => time.to_f.to_s}
856
853
  )
@@ -882,12 +879,12 @@ describe Zermelo::Associations::Multiple do
882
879
  create_child(parent, :id => '4', :emotion => 'indifferent', :timestamp => time)
883
880
  child = child_class.find_by_id('4')
884
881
 
885
- expect(redis.smembers("#{ck}::attrs:ids")).to eq(['4'])
882
+ expect(redis.zrange("#{ck}::attrs:ids", 0, -1)).to eq(['4'])
886
883
  expect(redis.zrange("#{pk}:8:assocs:children_ids", 0, -1)).to eq(['4'])
887
884
 
888
885
  parent.children.remove(child)
889
886
 
890
- expect(redis.smembers("#{ck}::attrs:ids")).to eq(['4']) # child not deleted
887
+ expect(redis.zrange("#{ck}::attrs:ids", 0, -1)).to eq(['4']) # child not deleted
891
888
  expect(redis.zrange("#{pk}:8:assocs:children_ids", 0, -1)).to eq([]) # but association is
892
889
  end
893
890
 
@@ -898,7 +895,6 @@ describe Zermelo::Associations::Multiple do
898
895
  expect(redis.keys).to match_array(["#{pk}::attrs:ids",
899
896
  "#{pk}:8:assocs:children_ids",
900
897
  "#{ck}::attrs:ids",
901
- "#{ck}::indices:by_timestamp",
902
898
  "#{ck}::indices:by_emotion:string:upset",
903
899
  "#{ck}:6:attrs",
904
900
  "#{ck}:6:assocs:belongs_to"])
@@ -906,7 +902,6 @@ describe Zermelo::Associations::Multiple do
906
902
  parent.destroy
907
903
 
908
904
  expect(redis.keys).to match_array(["#{ck}::attrs:ids",
909
- "#{ck}::indices:by_timestamp",
910
905
  "#{ck}::indices:by_emotion:string:upset",
911
906
  "#{ck}:6:attrs"])
912
907
  end
@@ -12,10 +12,10 @@ describe Zermelo::Associations::RangeIndex do
12
12
 
13
13
  module ZermeloExamples
14
14
  class RedisRangeIndex
15
- include Zermelo::Records::Redis
15
+ include Zermelo::Records::RedisSet
16
16
  define_attributes :created_at => :timestamp
17
- validates :created_at, :presence => true
18
17
  range_index_by :created_at
18
+ validates :created_at, :presence => true
19
19
  end
20
20
  end
21
21
 
@@ -42,13 +42,13 @@ describe Zermelo::Associations::Singular do
42
42
 
43
43
  module ZermeloExamples
44
44
  class AssociationsHasOneParentRedis
45
- include Zermelo::Records::Redis
45
+ include Zermelo::Records::RedisSet
46
46
  has_one :child, :class_name => 'ZermeloExamples::AssociationsHasOneChildRedis',
47
47
  :inverse_of => :parent
48
48
  end
49
49
 
50
50
  class AssociationsHasOneChildRedis
51
- include Zermelo::Records::Redis
51
+ include Zermelo::Records::RedisSet
52
52
  belongs_to :parent, :class_name => 'ZermeloExamples::AssociationsHasOneParentRedis',
53
53
  :inverse_of => :child
54
54
  end
@@ -10,7 +10,7 @@ describe Zermelo::Associations::UniqueIndex do
10
10
 
11
11
  module ZermeloExamples
12
12
  class RedisUniqueIndex
13
- include Zermelo::Records::Redis
13
+ include Zermelo::Records::RedisSet
14
14
  define_attributes :name => :string
15
15
  validates :name, :presence => true
16
16
  unique_index_by :name
@@ -229,7 +229,7 @@ describe Zermelo::Filter do
229
229
 
230
230
  module ZermeloExamples
231
231
  class FilterRedis
232
- include Zermelo::Records::Redis
232
+ include Zermelo::Records::RedisSet
233
233
  define_attributes :name => :string,
234
234
  :active => :boolean,
235
235
  :created_at => :timestamp
@@ -8,12 +8,12 @@ describe Zermelo::Locks::RedisLock, :redis => true do
8
8
 
9
9
  module Zermelo
10
10
  class RedisLockExample
11
- include Zermelo::Records::Redis
11
+ include Zermelo::Records::RedisSet
12
12
  define_attributes :name => :string
13
13
  end
14
14
 
15
15
  class AnotherExample
16
- include Zermelo::Records::Redis
16
+ include Zermelo::Records::RedisSet
17
17
  define_attributes :age => :integer
18
18
  end
19
19
  end
@@ -89,7 +89,7 @@ describe Zermelo::Records::InstMethods do
89
89
 
90
90
  module ZermeloExamples
91
91
  class InstanceMethodsRedis
92
- include Zermelo::Records::Redis
92
+ include Zermelo::Records::RedisSet
93
93
 
94
94
  define_attributes :name => :string
95
95
  validates :name, :presence => true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zermelo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ali Graham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-15 00:00:00.000000000 Z
11
+ date: 2015-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -137,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
137
  requirements:
138
138
  - Redis and/or InfluxDB, and the related gems
139
139
  rubyforge_project:
140
- rubygems_version: 2.4.8
140
+ rubygems_version: 2.4.5.1
141
141
  signing_key:
142
142
  specification_version: 4
143
143
  summary: ActiveModel-based set-theoretic ORM for Redis/InfluxDB