dm-redis-adapter 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +33 -0
- data/lib/dm_redis.rb +64 -21
- metadata +2 -2
data/README.textile
CHANGED
@@ -48,6 +48,39 @@ Setup your adapter, define your models and properties:
|
|
48
48
|
|
49
49
|
Now you can use redis in a ORM style, and take advantage of all of the amazing things that DataMapper offers.
|
50
50
|
|
51
|
+
If you want to do finds on specific String fields, add an index:
|
52
|
+
|
53
|
+
<pre>
|
54
|
+
<code>
|
55
|
+
class Coffee
|
56
|
+
include DataMapper::Resource
|
57
|
+
|
58
|
+
property :id, Serial
|
59
|
+
property :description, String, :index => true
|
60
|
+
end
|
61
|
+
|
62
|
+
Coffee.create(:description => "Notes of crude oil and sulphur")
|
63
|
+
Coffee.first(:description => "Notes of crude oil and sulphur") # will now work
|
64
|
+
</code>
|
65
|
+
</pre>
|
66
|
+
|
67
|
+
Validations on unique fields are now supported through indices and dm-validations:
|
68
|
+
|
69
|
+
<pre>
|
70
|
+
<code>
|
71
|
+
class Crumblecake
|
72
|
+
include DataMapper::Resource
|
73
|
+
validates_is_unique :flavor
|
74
|
+
|
75
|
+
property :id, Serial
|
76
|
+
property :flavor, String, :index => true
|
77
|
+
end
|
78
|
+
|
79
|
+
Crumblecake.create(:flavor => "snozzbler")
|
80
|
+
Crumblecake.new(:flavor => "snozzbler").valid? # false (of course! Who ever heard of a snozzbler crumblecake?)
|
81
|
+
</code>
|
82
|
+
</pre>
|
83
|
+
|
51
84
|
h1. Badass contributors
|
52
85
|
|
53
86
|
* <a href="http://github.com/aeden">Anthony Eden (aeden)</a> Gem cleanup, update to jeweler
|
data/lib/dm_redis.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'redis'
|
2
|
+
require "base64"
|
2
3
|
|
3
4
|
module DataMapper
|
4
5
|
module Adapters
|
5
|
-
Extlib::Inflection.word 'redis'
|
6
|
-
|
7
6
|
class RedisAdapter < AbstractAdapter
|
8
7
|
##
|
9
8
|
# Used by DataMapper to put records into the redis data-store: "INSERT" in SQL-speak.
|
@@ -18,9 +17,8 @@ module DataMapper
|
|
18
17
|
def create(resources)
|
19
18
|
resources.each do |resource|
|
20
19
|
initialize_serial(resource, @redis.incr("#{resource.model.to_s.downcase}:#{redis_key_for(resource.model)}:serial"))
|
21
|
-
@redis.set_add(
|
20
|
+
@redis.set_add(key_set_for(resource.model), resource.key)
|
22
21
|
end
|
23
|
-
|
24
22
|
update_attributes(resources)
|
25
23
|
end
|
26
24
|
|
@@ -63,9 +61,9 @@ module DataMapper
|
|
63
61
|
# @api semipublic
|
64
62
|
def update(attributes, collection)
|
65
63
|
attributes = attributes_as_fields(attributes)
|
66
|
-
|
64
|
+
|
67
65
|
records_to_update = records_for(collection.query)
|
68
|
-
records_to_update.each {
|
66
|
+
records_to_update.each {|r| r.update(attributes)}
|
69
67
|
update_attributes(collection)
|
70
68
|
end
|
71
69
|
|
@@ -81,14 +79,17 @@ module DataMapper
|
|
81
79
|
#
|
82
80
|
# @api semipublic
|
83
81
|
def delete(collection)
|
84
|
-
|
82
|
+
records_for(collection.query).each do |record|
|
85
83
|
collection.query.model.properties.each do |p|
|
86
84
|
@redis.delete("#{collection.query.model.to_s.downcase}:#{record[redis_key_for(collection.query.model)]}:#{p.name}")
|
87
85
|
end
|
88
|
-
@redis.set_delete(
|
86
|
+
@redis.set_delete(key_set_for(collection.query.model), record[redis_key_for(collection.query.model)])
|
87
|
+
collection.query.model.properties.select {|p| p.index}.each do |p|
|
88
|
+
@redis.set_delete("#{collection.query.model.to_s.downcase}:#{p.name}:#{encode(record[p.name])}", record[redis_key_for(collection.query.model)])
|
89
|
+
end
|
89
90
|
end
|
90
91
|
end
|
91
|
-
|
92
|
+
|
92
93
|
private
|
93
94
|
|
94
95
|
##
|
@@ -97,9 +98,8 @@ module DataMapper
|
|
97
98
|
# @param [DataMapper::Model] model
|
98
99
|
# The query used to locate the resources to be deleted.
|
99
100
|
#
|
100
|
-
# @return [
|
101
|
-
#
|
102
|
-
# each record
|
101
|
+
# @return [String]
|
102
|
+
# A string representation of the string key for this model
|
103
103
|
#
|
104
104
|
# @api private
|
105
105
|
def redis_key_for(model)
|
@@ -107,15 +107,19 @@ module DataMapper
|
|
107
107
|
end
|
108
108
|
|
109
109
|
##
|
110
|
-
# Saves each
|
110
|
+
# Saves each resource to the redis data store
|
111
111
|
#
|
112
|
-
# @param [Array]
|
113
|
-
# An array of
|
112
|
+
# @param [Array] Resources
|
113
|
+
# An array of resource to save
|
114
114
|
#
|
115
115
|
# @api private
|
116
116
|
def update_attributes(resources)
|
117
117
|
resources.each do |resource|
|
118
|
-
resource.
|
118
|
+
resource.model.properties.select {|p| p.index}.each do |property|
|
119
|
+
@redis.set_add("#{resource.model.to_s.downcase}:#{property.name}:#{encode(resource[property.name.to_s])}", resource.key)
|
120
|
+
end
|
121
|
+
|
122
|
+
resource.attributes(:field).each do |property, value|
|
119
123
|
next if resource.key.include?(property)
|
120
124
|
@redis["#{resource.model.to_s.downcase}:#{resource.key}:#{property}"] = value unless value.nil?
|
121
125
|
end
|
@@ -134,21 +138,30 @@ module DataMapper
|
|
134
138
|
# @api private
|
135
139
|
def records_for(query)
|
136
140
|
keys = []
|
137
|
-
|
138
|
-
|
139
|
-
|
141
|
+
|
142
|
+
query.conditions.operands.select {|o| o.is_a?(DataMapper::Query::Conditions::EqualToComparison)}.each do |o|
|
143
|
+
if query.model.key.include?(o.subject)
|
144
|
+
if @redis.set_member?(key_set_for(query.model), o.value)
|
145
|
+
keys << {"#{redis_key_for(query.model)}" => o.value}
|
146
|
+
end
|
147
|
+
return keys
|
140
148
|
end
|
149
|
+
find_matches(query, o).each do |k|
|
150
|
+
keys << {"#{redis_key_for(query.model)}" => k, "#{o.subject.name}" => o.value}
|
151
|
+
end
|
152
|
+
return keys
|
141
153
|
end
|
142
154
|
|
143
155
|
if query.limit
|
144
|
-
@redis.sort(
|
156
|
+
@redis.sort(key_set_for(query.model), :limit => [query.offset, query.limit]).each do |val|
|
145
157
|
keys << {"#{redis_key_for(query.model)}" => val.to_i}
|
146
158
|
end
|
159
|
+
return keys
|
147
160
|
end
|
148
161
|
|
149
162
|
# Keys are empty, fall back and load all the values for this model
|
150
163
|
if keys.empty?
|
151
|
-
@redis.set_members(
|
164
|
+
@redis.set_members(key_set_for(query.model)).each do |val|
|
152
165
|
keys << {"#{redis_key_for(query.model)}" => val.to_i}
|
153
166
|
end
|
154
167
|
end
|
@@ -156,6 +169,36 @@ module DataMapper
|
|
156
169
|
keys
|
157
170
|
end
|
158
171
|
|
172
|
+
##
|
173
|
+
# Return the key string for the set that contains all keys for a particular resource
|
174
|
+
#
|
175
|
+
# @return String
|
176
|
+
# The string key for the :all set
|
177
|
+
# @api private
|
178
|
+
def key_set_for(model)
|
179
|
+
"#{model.to_s.downcase}:#{redis_key_for(model)}:all"
|
180
|
+
end
|
181
|
+
|
182
|
+
##
|
183
|
+
# Find a matching entry for a query
|
184
|
+
#
|
185
|
+
# @return [Array]
|
186
|
+
# Array of id's of all members matching the query
|
187
|
+
# @api private
|
188
|
+
def find_matches(query, operand)
|
189
|
+
@redis.set_members("#{query.model.to_s.downcase}:#{operand.subject.name}:#{encode(operand.value)}")
|
190
|
+
end
|
191
|
+
|
192
|
+
##
|
193
|
+
# Base64 encode a value as a string key for an index
|
194
|
+
#
|
195
|
+
# @return String
|
196
|
+
# Base64 representation of a value
|
197
|
+
# @api private
|
198
|
+
def encode(value)
|
199
|
+
Base64.encode64(value.to_s).gsub("\n", "")
|
200
|
+
end
|
201
|
+
|
159
202
|
##
|
160
203
|
# Make a new instance of the adapter. The @redis ivar is the 'data-store'
|
161
204
|
# for this adapter.
|
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.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Herrera
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-03-01 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|