silver 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -7,27 +7,45 @@ Silver is a lightweight, redis-backed database cacher and indexer.
7
7
  As it says on the tin, Silver is going to make your database queries much faster. Now it is no secret that Redis is fantastic to use as a cache/index. However, you have to write the same boilerplate to use it as cache over and over: find most recent cached entry, look for newer entries in the database, cache it to redis, combine with old results. Rinse, repeat.
8
8
  The goal of Silver is so that you never have to do that again. Rather than connecting to the database/service for you, you simply wrap your calls in Silver and it does the rest. This means you can use silver to speed up calls to databases, calls APIs, CURLS, really whatever you want.
9
9
 
10
+ ### Dependency Note
11
+ Silver require a version of Redis >= 2.0 running on your computer
12
+ Runtime gem dependincies are:
13
+
14
+ * redis ~> 2.1.1
15
+ * yajl-ruby >= 0.7.7
16
+ * text ~> 0.2.0
17
+
10
18
  ### A Simple Caching Example
11
19
 
12
20
  First make sure you have Silver installed.
21
+
13
22
  gem install silver
23
+
14
24
  Now, let's pretend you have an app that queries your database for entries frequently. Entries are added frequently. Furthermore, you only want Entries that come from a specific blog, blog #12. Also you want to grab something from an association of the Entry row in the database. Let's say the author's name.
15
25
  First, instantiate a new cache object.
26
+
16
27
  cache = Silver::Cache.new("12_entries","created_time") do |date|
17
28
  Entry.all(:order => :created_time.desc, :created_time.gt => date, :blog_id => 12)
18
29
  end
30
+
19
31
  The first paramater passed to the constructor is the name you want to give to this cache in Redis as Silver allows to creates as many caches for different queries as you would like. The second paramater is the name of the field that you will be using to determine if there are new entries. Finally, you pass the constructor a block that will receive the date of the newest cached entry from Redis. You must return the entries in reverse chronological order for Silver to be able to keep them in order. Silver will then query the database/service for newer entries when the instance's find method is called.
32
+
20
33
  results = cache.find do |entry|
21
34
  attrs = entry.attributes
22
35
  author = {:author_name => entry.author[:name]}
23
36
  attrs.merge author
24
37
  end
38
+
25
39
  The find method of a cache instance takes a block that will be called for every new entry. The results of the block call should be a hash that will be stored in the cache. The whole thing will be converted into JSON and stashed in the Redis cache. From now on the database will never have to be hit again to return this value. The find method returns an array of all the results old and new from the Redis cache.
26
40
  If you just want to read from the cache without hitting the database, simply call find without a block and with a single param: false
41
+
27
42
  results = cache.find(false)
43
+
28
44
  Currently, the cache does not support the changing of cached entries and is, thus, intended for data that is unlikely to change once it has been written to the database. This feature will be included in future releases of Silver.
29
45
  Finally, Silver provides a cull method.
46
+
30
47
  cache.cull(30)
48
+
31
49
  This will cut the Redis cache down to the 30 most recent items.
32
50
 
33
51
  ### A Simple Indexing Example
@@ -35,20 +53,28 @@ This will cut the Redis cache down to the 30 most recent items.
35
53
  However, Silver is not just a simple cache. It can also be used to index a database. It is optimized to index based on short text, such as names, captions, tag lists, excerpts, tweets etc. There is nothing stopping you from using on longer fields such as body text except the size of your memory alloted to Redis. Silver uses a stupidly simple fuzzy text search. The search will likely be augmented in the future.
36
54
  Here's how you would index a mess of photos by their captions, falling back on their filename if no caption is given.
37
55
  First, instantiate a new index object.
56
+
38
57
  index = Silver::Index.new("blog_pictures","created_time") do |date|
39
58
  Picture.all(:order => :created_time.desc, :created_time.gt => date)
40
59
  end
60
+
41
61
  This is the same deal as before with Silver::Cache: redis key name, time field, ordering block.
42
62
  Next, call the find_and_update method of the instance.
63
+
43
64
  index.find_and_update do |result|
44
65
  output = result.label || result.filename || ""
45
66
  id = result.id
46
67
  [id,output]
47
68
  end
69
+
48
70
  Find_and_update takes a block that will be called for each db-fetched result. This block should return a two item array of the row's id, first, and the value we are using for indexing second. As you can see in the example, Silver allows you to mix fields to use to index. It let's you do anything you want actually as long as an id and a corresponding value are returned. After calling find_and_update, your database is indexed and ready to be searched. Say, we wanted to search for photos of "Barack Obama":
71
+
49
72
  search = Silver::Search.new("Barack Obama","blog_pictures")
73
+
50
74
  The constructor takes a string to search for and the name of Redis key storing the index. To actually perform the search:
75
+
51
76
  search.perform{|id| Picture.get(id)}
77
+
52
78
  The perform method takes a block that will be passed the ids of all the id's whose indexes match the query. Perform will return an array of database/service objects for you to then interact with as you please.
53
79
 
54
80
  ### A note about the shortcoming of the search.
@@ -58,9 +84,13 @@ As Silver is currently in beta, it's search could use some work (feel free to co
58
84
  ### Non-standard configurations
59
85
 
60
86
  Every initializer in Silver takes, in addition to the parameters shown above, an optional options hash for Redis as the third parameter.
87
+
61
88
  cache = Silver::Cache.new("12_entries","created_time",{:host => "127.0.0.1",:port => "6969"})
89
+
62
90
  Also, the search initializer for Silver's indexing takes optional number and offset paramater for pagination. Default is no offest and 30 results returned.
91
+
63
92
  search = Silver::Search.new("Barack Obama","blog_pictures",{:host => "127.0.0.1",:port => "6969"},50,10)
93
+
64
94
  This will return results 10-60.
65
95
 
66
96
  ### Rocco Annotated Source
data/lib/silver/search.rb CHANGED
@@ -38,7 +38,7 @@ module Silver
38
38
  phones = self.find_matching_phones(phones)
39
39
  phones
40
40
  end
41
- results = morphed_words.reduce{|memo,obj| memo & obj}.slice(@offset,@offset+@number)
41
+ results = morphed_words.reduce{|memo,obj| memo & obj}.slice(@offset,@number)
42
42
  results.map{|result| accessor.call(result)}
43
43
  end
44
44
 
data/silver.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{silver}
8
- s.version = "0.2.0"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Erik Hin-tone"]
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: silver
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 0
10
- version: 0.2.0
9
+ - 1
10
+ version: 0.2.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Erik Hin-tone
@@ -19,9 +19,9 @@ date: 2011-01-31 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- type: :development
22
+ name: rspec
23
23
  prerelease: false
24
- version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
27
  - - ~>
@@ -32,12 +32,12 @@ dependencies:
32
32
  - 3
33
33
  - 0
34
34
  version: 2.3.0
35
- name: rspec
36
- requirement: *id001
37
- - !ruby/object:Gem::Dependency
38
35
  type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
39
  prerelease: false
40
- version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
43
  - - ~>
@@ -48,12 +48,12 @@ dependencies:
48
48
  - 0
49
49
  - 0
50
50
  version: 1.0.0
51
- name: bundler
52
- requirement: *id002
53
- - !ruby/object:Gem::Dependency
54
51
  type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: jeweler
55
55
  prerelease: false
56
- version_requirements: &id003 !ruby/object:Gem::Requirement
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
59
  - - ~>
@@ -64,12 +64,12 @@ dependencies:
64
64
  - 5
65
65
  - 2
66
66
  version: 1.5.2
67
- name: jeweler
68
- requirement: *id003
69
- - !ruby/object:Gem::Dependency
70
67
  type: :development
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: rcov
71
71
  prerelease: false
72
- version_requirements: &id004 !ruby/object:Gem::Requirement
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ">="
@@ -78,12 +78,12 @@ dependencies:
78
78
  segments:
79
79
  - 0
80
80
  version: "0"
81
- name: rcov
82
- requirement: *id004
83
- - !ruby/object:Gem::Dependency
84
81
  type: :development
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ name: redis
85
85
  prerelease: false
86
- version_requirements: &id005 !ruby/object:Gem::Requirement
86
+ requirement: &id005 !ruby/object:Gem::Requirement
87
87
  none: false
88
88
  requirements:
89
89
  - - ~>
@@ -94,12 +94,12 @@ dependencies:
94
94
  - 1
95
95
  - 1
96
96
  version: 2.1.1
97
- name: redis
98
- requirement: *id005
99
- - !ruby/object:Gem::Dependency
100
97
  type: :development
98
+ version_requirements: *id005
99
+ - !ruby/object:Gem::Dependency
100
+ name: yajl-ruby
101
101
  prerelease: false
102
- version_requirements: &id006 !ruby/object:Gem::Requirement
102
+ requirement: &id006 !ruby/object:Gem::Requirement
103
103
  none: false
104
104
  requirements:
105
105
  - - ">="
@@ -110,12 +110,12 @@ dependencies:
110
110
  - 7
111
111
  - 7
112
112
  version: 0.7.7
113
- name: yajl-ruby
114
- requirement: *id006
115
- - !ruby/object:Gem::Dependency
116
113
  type: :development
114
+ version_requirements: *id006
115
+ - !ruby/object:Gem::Dependency
116
+ name: text
117
117
  prerelease: false
118
- version_requirements: &id007 !ruby/object:Gem::Requirement
118
+ requirement: &id007 !ruby/object:Gem::Requirement
119
119
  none: false
120
120
  requirements:
121
121
  - - ~>
@@ -126,12 +126,12 @@ dependencies:
126
126
  - 2
127
127
  - 0
128
128
  version: 0.2.0
129
- name: text
130
- requirement: *id007
131
- - !ruby/object:Gem::Dependency
132
129
  type: :development
130
+ version_requirements: *id007
131
+ - !ruby/object:Gem::Dependency
132
+ name: dm-core
133
133
  prerelease: false
134
- version_requirements: &id008 !ruby/object:Gem::Requirement
134
+ requirement: &id008 !ruby/object:Gem::Requirement
135
135
  none: false
136
136
  requirements:
137
137
  - - ~>
@@ -142,12 +142,12 @@ dependencies:
142
142
  - 0
143
143
  - 0
144
144
  version: 1.0.0
145
- name: dm-core
146
- requirement: *id008
147
- - !ruby/object:Gem::Dependency
148
145
  type: :development
146
+ version_requirements: *id008
147
+ - !ruby/object:Gem::Dependency
148
+ name: dm-sqlite-adapter
149
149
  prerelease: false
150
- version_requirements: &id009 !ruby/object:Gem::Requirement
150
+ requirement: &id009 !ruby/object:Gem::Requirement
151
151
  none: false
152
152
  requirements:
153
153
  - - ~>
@@ -158,12 +158,12 @@ dependencies:
158
158
  - 0
159
159
  - 0
160
160
  version: 1.0.0
161
- name: dm-sqlite-adapter
162
- requirement: *id009
161
+ type: :development
162
+ version_requirements: *id009
163
163
  - !ruby/object:Gem::Dependency
164
- type: :runtime
164
+ name: redis
165
165
  prerelease: false
166
- version_requirements: &id010 !ruby/object:Gem::Requirement
166
+ requirement: &id010 !ruby/object:Gem::Requirement
167
167
  none: false
168
168
  requirements:
169
169
  - - ~>
@@ -174,12 +174,12 @@ dependencies:
174
174
  - 1
175
175
  - 1
176
176
  version: 2.1.1
177
- name: redis
178
- requirement: *id010
179
- - !ruby/object:Gem::Dependency
180
177
  type: :runtime
178
+ version_requirements: *id010
179
+ - !ruby/object:Gem::Dependency
180
+ name: yajl-ruby
181
181
  prerelease: false
182
- version_requirements: &id011 !ruby/object:Gem::Requirement
182
+ requirement: &id011 !ruby/object:Gem::Requirement
183
183
  none: false
184
184
  requirements:
185
185
  - - ">="
@@ -190,12 +190,12 @@ dependencies:
190
190
  - 7
191
191
  - 7
192
192
  version: 0.7.7
193
- name: yajl-ruby
194
- requirement: *id011
195
- - !ruby/object:Gem::Dependency
196
193
  type: :runtime
194
+ version_requirements: *id011
195
+ - !ruby/object:Gem::Dependency
196
+ name: text
197
197
  prerelease: false
198
- version_requirements: &id012 !ruby/object:Gem::Requirement
198
+ requirement: &id012 !ruby/object:Gem::Requirement
199
199
  none: false
200
200
  requirements:
201
201
  - - ~>
@@ -206,12 +206,12 @@ dependencies:
206
206
  - 2
207
207
  - 0
208
208
  version: 0.2.0
209
- name: text
210
- requirement: *id012
209
+ type: :runtime
210
+ version_requirements: *id012
211
211
  - !ruby/object:Gem::Dependency
212
- type: :development
212
+ name: dm-core
213
213
  prerelease: false
214
- version_requirements: &id013 !ruby/object:Gem::Requirement
214
+ requirement: &id013 !ruby/object:Gem::Requirement
215
215
  none: false
216
216
  requirements:
217
217
  - - ~>
@@ -222,12 +222,12 @@ dependencies:
222
222
  - 0
223
223
  - 0
224
224
  version: 1.0.0
225
- name: dm-core
226
- requirement: *id013
227
- - !ruby/object:Gem::Dependency
228
225
  type: :development
226
+ version_requirements: *id013
227
+ - !ruby/object:Gem::Dependency
228
+ name: dm-sqlite-adapter
229
229
  prerelease: false
230
- version_requirements: &id014 !ruby/object:Gem::Requirement
230
+ requirement: &id014 !ruby/object:Gem::Requirement
231
231
  none: false
232
232
  requirements:
233
233
  - - ~>
@@ -238,8 +238,8 @@ dependencies:
238
238
  - 0
239
239
  - 0
240
240
  version: 1.0.0
241
- name: dm-sqlite-adapter
242
- requirement: *id014
241
+ type: :development
242
+ version_requirements: *id014
243
243
  description: A lightweight, Redis-backed cacher and indexer for databases, REST API's, really anything you can query.
244
244
  email: hinton.erik@gmail.com
245
245
  executables: []