dm-redis-adapter 0.5.3 → 0.6.0

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