dm-redis-adapter 0.5.3 → 0.6.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/README.textile CHANGED
@@ -8,8 +8,13 @@ Redis is a very fast key-value store with some interesting data structures added
8
8
 
9
9
  Marrying DataMapper to Redis allows for schema-less models, you can add fields at any time without having to create a migration. DataMapper also allows us to store non-native Redis types in the db, like Date fields.
10
10
 
11
+ h1. Upgrading
12
+
13
+ Please note that as of version 0.5.3 of the gem, the key names that are used for storage have changed and break compatibility with previous versions!
14
+
11
15
  h1. Changelog
12
16
 
17
+ * v0.5.3 Support for inheritance via sfeu and ujifgc, this version *breaks compatibility* with previous versions of the gem
13
18
  * v0.4.0 Support for dm-core v1.1.0
14
19
  * v0.3.0 Updates to support ruby 1.9.2 (thanks arbarlow!)
15
20
  * v0.2.1 Fixes to sorting
@@ -21,9 +26,9 @@ h1. Install
21
26
 
22
27
  Prerequisites:
23
28
  * Redis:
24
- ** <a href="http://code.google.com/p/redis/">Redis, v2.2 series</a>
29
+ ** <a href="http://code.google.com/p/redis/">Redis, >= v2.2 series</a>
25
30
 
26
- Install the dm-redis adapter:
31
+ Install the dm-redis-adapter:
27
32
  <pre>
28
33
  <code>
29
34
  > gem install dm-redis-adapter
@@ -98,4 +103,5 @@ h1. Badass contributors
98
103
  * <a href="http://github.com/bpo">brian p o'rourke (bpo)</a> Updates for newer versions of redis client and DM JSON type support, move to hash storage
99
104
  * <a href="http://github.com/arbarlow">Alex Barlow (arbarlow)</a> Fixes for ruby 1.9.2
100
105
  * <a href="http://github.com/jof">Jonathan Lassoff (jof)</a> Fixes to support textual keys
106
+ * <a href="http://github.com/sfeu">Sebastian Feuerstack (sfeu)</a> Fixes to support inheritance
101
107
 
@@ -1 +1 @@
1
- require 'dm-redis-adapter/adapter'
1
+ require 'dm-redis-adapter/adapter'
@@ -1,7 +1,6 @@
1
1
  require 'redis/connection/hiredis'
2
2
  require 'redis'
3
3
  require 'base64'
4
- require 'dm-core'
5
4
 
6
5
  module DataMapper
7
6
  module Adapters
@@ -92,12 +91,11 @@ module DataMapper
92
91
  #
93
92
  # @api semipublic
94
93
  def delete(collection)
95
- storage_name = collection.query.model.storage_name
96
94
  collection.each do |record|
97
- @redis.del("#{storage_name}:#{record[redis_key_for(collection.query.model)]}")
95
+ @redis.del("#{collection.query.model.to_s.downcase}:#{record[redis_key_for(collection.query.model)]}")
98
96
  @redis.srem(key_set_for(collection.query.model), record[redis_key_for(collection.query.model)])
99
97
  record.model.properties.select {|p| p.index}.each do |p|
100
- @redis.srem("#{storage_name}:#{p.name}:#{encode(record[p.name])}", record[redis_key_for(collection.query.model)])
98
+ @redis.srem("#{collection.query.model.to_s.downcase}:#{p.name}:#{encode(record[p.name])}", record[redis_key_for(collection.query.model)])
101
99
  end
102
100
  end
103
101
  end
@@ -114,6 +112,7 @@ module DataMapper
114
112
  def update_attributes(resources)
115
113
  storage_name = resources.first.model.storage_name
116
114
  resources.each do |resource|
115
+
117
116
  model = resource.model
118
117
  attributes = resource.dirty_attributes
119
118
 
@@ -124,6 +123,7 @@ module DataMapper
124
123
  properties_to_set = []
125
124
  properties_to_del = []
126
125
 
126
+
127
127
  fields = model.properties(self.name).select {|property| attributes.key?(property)}
128
128
  fields.each do |property|
129
129
  value = attributes[property]
@@ -171,29 +171,14 @@ module DataMapper
171
171
  keys
172
172
  end
173
173
 
174
- ##
175
- # Find records that match have a matching value
176
- #
177
- # @param [DataMapper::Query] query
178
- # The query used to locate the resources to be deleted.
179
- #
180
- # @param [DataMapper::Operation] the operation for the query
181
- #
182
- # @api private
183
- def perform_query(query, operand)
184
- storage_name = query.model.storage_name
185
-
186
- matched_records = []
187
- #p 'query: ' + query.inspect
188
- #p 'operand: ' + operand.inspect
189
-
174
+ def find_subject_and_value(query, operand)
190
175
  if operand.is_a?(DataMapper::Query::Conditions::NotOperation)
191
176
  subject = operand.first.subject
192
177
  value = operand.first.value
193
178
  elsif operand.subject.is_a?(DataMapper::Associations::ManyToOne::Relationship)
194
179
  subject = operand.subject.child_key.first
195
180
  value = if operand.is_a?(DataMapper::Query::Conditions::InclusionComparison)
196
- operand.value.map{|v|v[operand.subject.parent_key.first.name]}
181
+ operand.value.map{|v| v[operand.subject.parent_key.first.name]}
197
182
  else
198
183
  operand.value[operand.subject.parent_key.first.name]
199
184
  end
@@ -206,46 +191,76 @@ module DataMapper
206
191
  subject = subject.child_key.first
207
192
  end
208
193
 
209
- #p 'subject: ' + subject.inspect
210
- #p 'value: ' + value.inspect
194
+ return subject, value
195
+ end
196
+
197
+ ##
198
+ # Find records that match have a matching value
199
+ #
200
+ # @param [DataMapper::Query] query
201
+ # The query used to locate the resources to be deleted.
202
+ #
203
+ # @param [DataMapper::Operation] the operation for the query
204
+ #
205
+ # @api private
206
+ def perform_query(query, operand)
207
+ storage_name = query.model.storage_name
208
+ matched_records = []
209
+ subject, value = find_subject_and_value(query, operand)
211
210
 
212
- if query.model.key.include?(subject)
213
- if operand.is_a?(DataMapper::Query::Conditions::NotOperation)
214
- @redis.smembers(key_set_for(query.model)).each do |key|
215
- if operand.matches?(subject.typecast(key))
216
- matched_records << {redis_key_for(query.model) => key}
211
+ case operand
212
+ when DataMapper::Query::Conditions::NotOperation
213
+ if query.model.key.include?(subject)
214
+ @redis.smembers(key_set_for(query.model)).each do |key|
215
+ if operand.matches?(subject.typecast(key))
216
+ matched_records << {redis_key_for(query.model) => key}
217
+ end
217
218
  end
219
+ else
220
+ search_all_resources(query, operand, subject, matched_records)
218
221
  end
219
- elsif operand.is_a?(DataMapper::Query::Conditions::InclusionComparison)
220
- value.each do |val|
221
- if @redis.sismember(key_set_for(query.model), val)
222
- matched_records << {redis_key_for(query.model) => val}
222
+ when DataMapper::Query::Conditions::InclusionComparison
223
+ if query.model.key.include?(subject)
224
+ value.each do |val|
225
+ if @redis.sismember(key_set_for(query.model), val)
226
+ matched_records << {redis_key_for(query.model) => val}
227
+ end
223
228
  end
224
- end
225
- elsif @redis.sismember(key_set_for(query.model), value)
226
- matched_records << {redis_key_for(query.model) => value}
227
- end
228
- elsif subject.respond_to?( :index ) && subject.index
229
- if operand.is_a?(DataMapper::Query::Conditions::NotOperation)
230
- elsif operand.is_a?(DataMapper::Query::Conditions::InclusionComparison)
231
- value.each do |val|
232
- find_indexed_matches(subject, val).each do |k|
233
- matched_records << {redis_key_for(query.model) => k, "#{subject.name}" => val}
229
+ elsif subject.respond_to?(:index) && subject.index
230
+ value.each do |val|
231
+ find_indexed_matches(subject, val).each do |k|
232
+ matched_records << {redis_key_for(query.model) => k, "#{subject.name}" => val}
233
+ end
234
234
  end
235
+ else
236
+ search_all_resources(query, operand, subject, matched_records)
235
237
  end
236
- else
237
- find_indexed_matches(subject, value).each do |k|
238
- matched_records << {redis_key_for(query.model) => k, "#{subject.name}" => value}
238
+ when DataMapper::Query::Conditions::EqualToComparison
239
+ if query.model.key.include?(subject)
240
+ if @redis.sismember(key_set_for(query.model), value)
241
+ matched_records << {redis_key_for(query.model) => value}
242
+ end
243
+ elsif subject.respond_to?(:index) && subject.index
244
+ find_indexed_matches(subject, value).each do |k|
245
+ matched_records << {redis_key_for(query.model) => k, "#{subject.name}" => value}
246
+ end
239
247
  end
248
+ else # worst case here, loop through all members, typecast and match
249
+ search_all_resources(query, operand, subject, matched_records)
240
250
  end
241
- else # worst case, loop through each record and match
242
- @redis.smembers(key_set_for(query.model)).each do |key|
243
- if operand.matches?(subject.typecast(@redis.hget("#{storage_name}:#{key}", subject.name)))
244
- matched_records << {redis_key_for(query.model) => key}
245
- end
251
+ matched_records
252
+ end
253
+
254
+ ##
255
+ # Searches through each key :(
256
+ #
257
+ # @api private
258
+ def search_all_resources(query, operand, subject, matched_records)
259
+ @redis.smembers(key_set_for(query.model)).each do |key|
260
+ if operand.matches?(subject.typecast(@redis.hget("#{subject.model.storage_name}:#{key}", subject.name)))
261
+ matched_records << {redis_key_for(query.model) => key}
246
262
  end
247
263
  end
248
- matched_records
249
264
  end
250
265
 
251
266
  ##
@@ -38,11 +38,10 @@ describe DataMapper::Adapters::RedisAdapter do
38
38
  found.should == [@b,@c,@d]
39
39
  end
40
40
 
41
- # it fails
42
- #it 'should find Page.all :parent_id.not => @a.id' do
43
- # found = Page.all :parent_id.not => @a.id
44
- # found.should == [@a,@d]
45
- #end
41
+ it 'should find Page.all :parent_id.not => @a.id' do
42
+ found = Page.all :parent_id.not => @a.id
43
+ found.should == [@a,@d]
44
+ end
46
45
 
47
46
  it 'should find Page.all :parent => @a' do
48
47
  found = Page.all :parent => @a
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataMapper::Adapters::RedisAdapter do
4
+ before(:all) do
5
+ @adapter = DataMapper.setup(:default, {
6
+ :adapter => "redis",
7
+ :db => 15
8
+ })
9
+ end
10
+
11
+ after(:all) do
12
+ Redis.new(:db => 15).flushdb
13
+ end
14
+
15
+ describe "referential assosciations" do
16
+ it "should allow the assosciation to go both ways" do
17
+ class User
18
+ class Link
19
+ include DataMapper::Resource
20
+
21
+ # the person who is doing the following
22
+ belongs_to :follower, 'User', :key => true
23
+
24
+ # the person who is being followed
25
+ belongs_to :followed, 'User', :key => true
26
+ end
27
+
28
+ include DataMapper::Resource
29
+
30
+ property :id, Serial
31
+ property :full_name, String, :length => 255, :required => true
32
+ property :email, String, :length => 320, :required => true
33
+
34
+ has n, :links_to_followed_users, 'User::Link', :child_key => [:follower_id]
35
+ has n, :links_to_followers, 'User::Link', :child_key => [:followed_id]
36
+ has n, :followed_users, User, :through => :links_to_followed_users, :via => :followed
37
+ has n, :followers, User, :through => :links_to_followers, :via => :follower
38
+ end
39
+
40
+ DataMapper.finalize
41
+
42
+ user1 = User.create(:email => "joe@example.com", :full_name => "joe")
43
+ user2 = User.create(:email => "bob@example.com", :full_name => "bob")
44
+
45
+ user1.followed_users << user2
46
+ user1.save
47
+ #user2.links_to_followers.count.should == 1
48
+ end
49
+ end
50
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-redis-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-08 00:00:00.000000000 -08:00
13
- default_executable:
12
+ date: 2012-02-13 00:00:00.000000000Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: dm-core
17
- requirement: &70343134239820 !ruby/object:Gem::Requirement
16
+ requirement: &70281536321700 !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ! '>='
@@ -22,10 +21,10 @@ dependencies:
22
21
  version: 1.2.0
23
22
  type: :runtime
24
23
  prerelease: false
25
- version_requirements: *70343134239820
24
+ version_requirements: *70281536321700
26
25
  - !ruby/object:Gem::Dependency
27
26
  name: dm-types
28
- requirement: &70343134210860 !ruby/object:Gem::Requirement
27
+ requirement: &70281536319260 !ruby/object:Gem::Requirement
29
28
  none: false
30
29
  requirements:
31
30
  - - ! '>='
@@ -33,10 +32,10 @@ dependencies:
33
32
  version: 1.2.0
34
33
  type: :runtime
35
34
  prerelease: false
36
- version_requirements: *70343134210860
35
+ version_requirements: *70281536319260
37
36
  - !ruby/object:Gem::Dependency
38
37
  name: hiredis
39
- requirement: &70343134209560 !ruby/object:Gem::Requirement
38
+ requirement: &70281536311280 !ruby/object:Gem::Requirement
40
39
  none: false
41
40
  requirements:
42
41
  - - ~>
@@ -44,10 +43,10 @@ dependencies:
44
43
  version: 0.3.0
45
44
  type: :runtime
46
45
  prerelease: false
47
- version_requirements: *70343134209560
46
+ version_requirements: *70281536311280
48
47
  - !ruby/object:Gem::Dependency
49
48
  name: redis
50
- requirement: &70343134205940 !ruby/object:Gem::Requirement
49
+ requirement: &70281536305900 !ruby/object:Gem::Requirement
51
50
  none: false
52
51
  requirements:
53
52
  - - ~>
@@ -55,7 +54,7 @@ dependencies:
55
54
  version: '2.2'
56
55
  type: :runtime
57
56
  prerelease: false
58
- version_requirements: *70343134205940
57
+ version_requirements: *70281536305900
59
58
  description: DataMapper adapter for the Redis key-value database
60
59
  email: whoahbot@gmail.com
61
60
  executables: []
@@ -74,9 +73,9 @@ files:
74
73
  - spec/dm_redis_inheritenance_spec.rb
75
74
  - spec/dm_redis_spec.rb
76
75
  - spec/dm_redis_validations_spec.rb
76
+ - spec/self_referential_spec.rb
77
77
  - spec/spec_helper.rb
78
78
  - spec/textual_keys_spec.rb
79
- has_rdoc: true
80
79
  homepage: http://github.com/whoahbot/dm-redis-adapter
81
80
  licenses: []
82
81
  post_install_message:
@@ -92,7 +91,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
91
  version: '0'
93
92
  segments:
94
93
  - 0
95
- hash: 4147115164932724252
94
+ hash: 3387811137579107358
96
95
  required_rubygems_version: !ruby/object:Gem::Requirement
97
96
  none: false
98
97
  requirements:
@@ -101,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
100
  version: '0'
102
101
  requirements: []
103
102
  rubyforge_project:
104
- rubygems_version: 1.6.2
103
+ rubygems_version: 1.8.16
105
104
  signing_key:
106
105
  specification_version: 3
107
106
  summary: DataMapper adapter for the Redis key-value database
@@ -111,5 +110,6 @@ test_files:
111
110
  - spec/dm_redis_inheritenance_spec.rb
112
111
  - spec/dm_redis_spec.rb
113
112
  - spec/dm_redis_validations_spec.rb
113
+ - spec/self_referential_spec.rb
114
114
  - spec/spec_helper.rb
115
115
  - spec/textual_keys_spec.rb