redify 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- checksums.yaml.gz.sig +2 -0
- data.tar.gz.sig +1 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +173 -0
- data/Rakefile +7 -0
- data/lib/redify.rb +12 -0
- data/lib/redify/application.rb +44 -0
- data/lib/redify/base.rb +35 -0
- data/lib/redify/core.rb +140 -0
- data/lib/redify/model.rb +55 -0
- data/lib/redify/settings.rb +39 -0
- data/lib/redify/version.rb +3 -0
- data/pauloddr-public.pem +21 -0
- data/redify.gemspec +35 -0
- data/spec/redify/core_spec.rb +40 -0
- data/spec/redify_spec.rb +17 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/active_record.rb +28 -0
- data/spec/support/models.rb +24 -0
- data/spec/support/redis.rb +4 -0
- metadata +213 -0
- metadata.gz.sig +1 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OWI0M2E1ZmYzNzNmYzQ2Y2M0MGI0N2ZjY2Y2MzZhZTgxNjdjMWQyYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZTNhZjFiOGU5ZDE2ZTNlNjhiN2E4ZTUyNDkwNjY5N2ViNDZjMzdkOQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NWM3MGEyMmQyZTU5ZTMzODY5ZjYwZWM3OWIxN2U2NWIxODA2MDcyMzRkMDZl
|
10
|
+
MDQwYmFjYTM1ZjIxNGQzNzk5ZWE2MzMwYzgyMTQyMjE4YzQ2MzEyZDBkY2Fl
|
11
|
+
YmE5NDU3MDM3N2UxMDU5ZDhiNDViZDk4NDRjYjQwZDNjZTIyNjE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YzEyYjk2MDAxYjU1NWVlZDAzOWQwNDkxNGI4OTUwNjI4MzdhNDM0N2QwMmJi
|
14
|
+
Yjk3YzM3Njk0OGU1MWQwZWY3NmRhYTA4ODk2NTY0Njk2MmRhNGE0NGIyYThl
|
15
|
+
NDhjYWRlMDNlYjc3ZjUwZTAzYTNiNDBkODI4NmE4NDJiNzQ4ZjY=
|
checksums.yaml.gz.sig
ADDED
data.tar.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
�~��eU��5pe\��&3��*ߔ��
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Panayotis Procopiou
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
# Redify
|
2
|
+
|
3
|
+
[![Dependency Status][DS img]][Dependency Status] [![Code Climate](https://codeclimate.com/github/pauloddr/redify.png)](https://codeclimate.com/github/pauloddr/redify)
|
4
|
+
|
5
|
+
## State of Code
|
6
|
+
|
7
|
+
Redify is currently under development and is not ready for public usage yet.
|
8
|
+
|
9
|
+
## Introduction
|
10
|
+
|
11
|
+
Redify intends to act as a plug-and-play Redis layer for your ActiveRecord models. By adding the following to your models...
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
class Foo < ActiveRecord::Base
|
15
|
+
redify
|
16
|
+
# ... rest of your code ...
|
17
|
+
end
|
18
|
+
```
|
19
|
+
... a few common database operations will be done through Redis instead of ActiveRecord, increasing overall speed of queries and decreasing your database server access frequency.
|
20
|
+
|
21
|
+
## Considerations
|
22
|
+
|
23
|
+
Redify __will increase your server memory usage__, depending on data size that is stored into Redis. It will also likely increase the boot time of your application, since Redify loads all data into Redis upon model initialization. Please keep those in mind when using this gem.
|
24
|
+
|
25
|
+
|
26
|
+
## Requirements
|
27
|
+
|
28
|
+
Instead of directly connecting into Redis itself, Redify requires an already connected handler that responds to Redis commands (like `get`, `hmget`, etc), so it is not restricted to a specific Redis client.
|
29
|
+
|
30
|
+
It works best with models which primary keys are either numeric or strings without any special characters, since they are used to compose key names in Redis.
|
31
|
+
|
32
|
+
Redify requires ActiveSupport ~> 3.0.
|
33
|
+
|
34
|
+
|
35
|
+
## Installation
|
36
|
+
|
37
|
+
Add this line to your application's Gemfile:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
gem 'redify', :git => 'git://github.com/pauloddr/redify.git'
|
41
|
+
```
|
42
|
+
|
43
|
+
And then execute:
|
44
|
+
|
45
|
+
$ bundle
|
46
|
+
|
47
|
+
Or install it yourself as:
|
48
|
+
|
49
|
+
$ gem install redify
|
50
|
+
|
51
|
+
|
52
|
+
## Setting Up
|
53
|
+
|
54
|
+
You can set up default options in `Redify::Settings` in your initializer scripts. The following example assumes you have defined a `$redis` variable elsewhere in your application pointing to a handler that responds to Redis commands:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
Redify::Settings.default_handler = $redis
|
58
|
+
```
|
59
|
+
|
60
|
+
You can define a namespace to be prepended to every key handled by Redify. By default, this namespace equals to `"Redify"` unless you set this option. A couple examples for Rails applications:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# MyApplication:production:*
|
64
|
+
Redify::Settings.namespace = "#{Rails.application.name}:#{Rails.env}"
|
65
|
+
|
66
|
+
# MyApplication:1.2.0:*
|
67
|
+
Redify::Settings.namespace = "#{Rails.application.name}:#{Rails.configuration.assets.version}"
|
68
|
+
```
|
69
|
+
|
70
|
+
## Redis Structure
|
71
|
+
|
72
|
+
Considering a model called `User` and an empty namespace, Redify will automatically generate the following keys in Redis when you "redify" a model:
|
73
|
+
|
74
|
+
- `Users` - a hash with extended data about the model with the following fields:
|
75
|
+
- `field_names` - a string with a comma-separated, ordered list of field names.
|
76
|
+
- `field_types` - a string with a comma-separated, ordered list of field types. Possible values are: `string`, `number`, `float`, `date`, `datetime` and `boolean`.
|
77
|
+
- `associations` - a string with a comma-separated list of associations that are "redified' for the model.
|
78
|
+
- `redify_status` - internal status of model "redification". Possible values are `"LOADING"` and `"READY"`.
|
79
|
+
- `Users:All` - an ordered list of primary keys from Users.
|
80
|
+
- `User:N` (for each record) - an hash containing information about a single record, where `N` is the record primary key.
|
81
|
+
|
82
|
+
When you throw in an associated model called `Post`, where `user has_many posts`, you also get:
|
83
|
+
|
84
|
+
- `Posts`
|
85
|
+
- `Posts:All`
|
86
|
+
- `Post:N` (for each record)
|
87
|
+
- `User:N:Posts` (for each `User`) - an ordered list of Post IDs that belong to `User#N`.
|
88
|
+
|
89
|
+
|
90
|
+
## Operations
|
91
|
+
|
92
|
+
Redify will use Redis for the following common operations:
|
93
|
+
|
94
|
+
- `User.all`
|
95
|
+
- `User.find N`
|
96
|
+
- `User.first(n)` and `User.last(n)`
|
97
|
+
- `User#Posts` (associations)
|
98
|
+
|
99
|
+
Redify will fall back to ActiveRecord on more complex queries until it works with more finders and options.
|
100
|
+
|
101
|
+
|
102
|
+
## Initialization Options
|
103
|
+
|
104
|
+
Upon "redification" of a model, you can pass some extended options.
|
105
|
+
|
106
|
+
### `:with_associations => [...]`
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
class User < ActiveRecord::Base
|
110
|
+
has_many :posts
|
111
|
+
redify :with_associations => [:posts]
|
112
|
+
# ...
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
You can also pass `:all` instead of an array of associations to always redify all associations.
|
117
|
+
|
118
|
+
### `:through => <redis_handler>`
|
119
|
+
|
120
|
+
Redify will use the default Redis handler passed to `Redify::Settings.default_handler` unless you specify this option. Namespace rules still apply to all Redis instances in use.
|
121
|
+
|
122
|
+
|
123
|
+
## Finder Options
|
124
|
+
|
125
|
+
### `:skip_redify => true`
|
126
|
+
|
127
|
+
Example:
|
128
|
+
```ruby
|
129
|
+
User.all :skip_redify => true
|
130
|
+
```
|
131
|
+
|
132
|
+
Use this option if for some reason you want to go straight to ActiveRecord.
|
133
|
+
|
134
|
+
### `:as => :hash`
|
135
|
+
|
136
|
+
Example:
|
137
|
+
```ruby
|
138
|
+
User.all :as => :hash
|
139
|
+
```
|
140
|
+
|
141
|
+
Redify will return raw hashes instead of ActiveRecord models. This will yield the fastest speeds. Use this if you can affort not relying on ActiveRecord instances.
|
142
|
+
|
143
|
+
If the model has any redified associations, they will be available as an array of IDs. For example, when an user has many posts and they're included in the query (as in, `:include => :posts`), its hash will return as:
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
{id: 1, name: "...", ..., post_ids: [1, 2, 3,...]}
|
147
|
+
```
|
148
|
+
|
149
|
+
## Scalability and Maintenance
|
150
|
+
|
151
|
+
Redify is intended to work with multiple servers running multiple spawns of the same application, all sharing the same Redis connection. Data integrity is kept tight through a solid namespace composition and some under-the-hood work (keep reading) within the gem. That way, Redis can work as a large pool of data serving multiple applications in the same or different servers.
|
152
|
+
|
153
|
+
To make sure multiple instances don't interfere with each other, Redify sets a root-level namespace in Redis called `RedifyApps`, followed by the server hostname, and finally the application namespace. This structure is then used to keep track of all processes running Redify applications. It maintains itself on demand by running a sanity check upon application boot, deleting old keys from applications that are no longer being used by any active processes.
|
154
|
+
|
155
|
+
|
156
|
+
## Wishlist (TODO)
|
157
|
+
|
158
|
+
In no particular order...
|
159
|
+
|
160
|
+
- make it work with more finders
|
161
|
+
- implement a simple index system with tags (a.k.a. "poor man's elastic search")
|
162
|
+
|
163
|
+
## Contributing
|
164
|
+
|
165
|
+
1. Fork it
|
166
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
167
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
168
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
169
|
+
5. Create new Pull Request
|
170
|
+
|
171
|
+
[Dependency Status]: https://gemnasium.com/pauloddr/redify
|
172
|
+
|
173
|
+
[DS img]: https://gemnasium.com/pauloddr/redify.png
|
data/Rakefile
ADDED
data/lib/redify.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
require "redify/version"
|
4
|
+
require "redify/settings"
|
5
|
+
require "redify/core"
|
6
|
+
require "redify/base"
|
7
|
+
require "redify/model"
|
8
|
+
require "redify/application"
|
9
|
+
|
10
|
+
Redify::Settings.set_default_options
|
11
|
+
|
12
|
+
ActiveRecord::Base.__send__(:include, Redify::Base)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Redify
|
4
|
+
|
5
|
+
class Application
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def install
|
10
|
+
return false unless installable?
|
11
|
+
p, n, h = get_data
|
12
|
+
h.sadd("#{p}", n)
|
13
|
+
h.sadd("#{p}:#{n}:PIDs", $$)
|
14
|
+
end
|
15
|
+
|
16
|
+
def uninstall
|
17
|
+
p, n, h = get_data
|
18
|
+
h.srem("#{p}", n)
|
19
|
+
h.srem("#{p}:#{n}:PIDs", $$)
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def prefix
|
26
|
+
"RedifyApps:#{Socket.gethostname}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def installable?
|
30
|
+
_, n, h = get_data
|
31
|
+
n && h
|
32
|
+
end
|
33
|
+
|
34
|
+
# returns prefix, namespace and handler
|
35
|
+
def get_data
|
36
|
+
[prefix, Redify::Settings.namespace, Redify::Settings.default_handler]
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/lib/redify/base.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Redify
|
2
|
+
module Base
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
# Call this from an ActiveRecord model to activate Redify features.
|
9
|
+
def redify(options = {})
|
10
|
+
|
11
|
+
# includes main Redify functionality
|
12
|
+
__send__ :include, Redify::Model
|
13
|
+
|
14
|
+
# Redis handler for the model, if specified
|
15
|
+
__send__ :redify_handler=, options[:through]
|
16
|
+
|
17
|
+
# caches some keys to avoid unnecessary calls to get_*_key_name_for() methods
|
18
|
+
__send__ :redify_keys=, {
|
19
|
+
:resource => Redify::Core.get_namespaced_key_name_for(:resource => self),
|
20
|
+
:all => Redify::Core.get_namespaced_key_name_for(:resource => self, :collection => "All")
|
21
|
+
}
|
22
|
+
|
23
|
+
# load data into Redis for the first time
|
24
|
+
Redify::Core.initialize_resource(self)
|
25
|
+
|
26
|
+
# hooks
|
27
|
+
after_create lambda { Redify::Core.after_create(self) }
|
28
|
+
after_save lambda { Redify::Core.after_save(self) }
|
29
|
+
after_destroy lambda { Redify::Core.after_destroy(self) }
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/redify/core.rb
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
module Redify
|
2
|
+
class Core
|
3
|
+
class << self
|
4
|
+
|
5
|
+
# Valid options:
|
6
|
+
# :resource - ActiveRecord model class (User)
|
7
|
+
# :collection - camel-cased string denoting collection name
|
8
|
+
# :record - a single record instance (User.find 1)
|
9
|
+
def get_namespaced_key_name_for(options)
|
10
|
+
key_name = get_key_name_for(options)
|
11
|
+
namespace = Redify::Settings.namespace
|
12
|
+
namespace ? "#{namespace}:#{key_name}" : key_name
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the key name without the namespace.
|
16
|
+
def get_key_name_for(options)
|
17
|
+
if options[:collection]
|
18
|
+
get_key_name_for_collection(options)
|
19
|
+
elsif options[:record]
|
20
|
+
get_key_name_for_record(options[:record])
|
21
|
+
elsif options[:resource] && options[:id]
|
22
|
+
get_key_name_for_resource_and_id(options)
|
23
|
+
elsif options[:resource]
|
24
|
+
get_key_name_for_resource(options[:resource])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_key_name_for_collection(options)
|
29
|
+
key_name = get_key_name_for_resource(options[:resource])
|
30
|
+
if options[:collection] == "All"
|
31
|
+
key_name << ":All"
|
32
|
+
else
|
33
|
+
key_name << ":Collections:#{options[:collection]}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_key_name_for_record(record)
|
38
|
+
"#{record.class.name}:#{record.id}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_key_name_for_resource(resource)
|
42
|
+
"#{ActiveSupport::Inflector.pluralize(resource.to_s)}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_key_name_for_resource_and_id(options)
|
46
|
+
"#{options[:resource].to_s}:#{options[:id]}"
|
47
|
+
end
|
48
|
+
|
49
|
+
# Valid options:
|
50
|
+
# :resource - ActiveRecord model class (User)
|
51
|
+
# :id - record primary key
|
52
|
+
def fetch_record(options)
|
53
|
+
|
54
|
+
resource = options[:resource]
|
55
|
+
|
56
|
+
return nil unless resource
|
57
|
+
return resource.find(options[:id], :skip_redify => true) unless resource.redify_handler # Redis is unavailable
|
58
|
+
return synchronize(:resource => resource, :id => options[:id])
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
# fetch first or last N entries
|
63
|
+
def fetch_records_by_edge(resource, last = false, count = 1)
|
64
|
+
# TODO implement COUNT
|
65
|
+
edge_id = redify_handler.lindex resource.redify_keys[:all], (last ? -1 : 0)
|
66
|
+
edge_id ? Redify::Core.fetch_record(:resource => resource, :id => edge_id) : nil
|
67
|
+
end
|
68
|
+
|
69
|
+
# Loads all records into Redis upon initialization
|
70
|
+
def initialize_resource(resource)
|
71
|
+
|
72
|
+
redis = resource.redify_handler
|
73
|
+
resource_status = redis.hget(resource.redify_keys[:resource], 'status')
|
74
|
+
|
75
|
+
if resource_status == "READY"
|
76
|
+
puts "[Redify] Resource #{resource} is already loaded."
|
77
|
+
elsif resource_status == 'LOADING'
|
78
|
+
puts "[Redify] Resource #{resource} is being loaded by another process."
|
79
|
+
else
|
80
|
+
puts "[Redify] Initializing resource #{resource}"
|
81
|
+
redify_all_records(resource, redis)
|
82
|
+
puts "... finished"
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def redify_all_records(resource, redis)
|
88
|
+
flush_keys(resource)
|
89
|
+
resource_key = resource.redify_keys[:resource]
|
90
|
+
redis.hset(resource_key, 'status', 'LOADING')
|
91
|
+
resource.find(:all, :skip_redify => true).each do |r|
|
92
|
+
redify_record(r)
|
93
|
+
redis.rpush(redify_keys[:all], r.id)
|
94
|
+
end
|
95
|
+
# TODO load associations and scopes
|
96
|
+
redis.hset(resource_key, 'status', 'READY')
|
97
|
+
end
|
98
|
+
|
99
|
+
# Turns an ActiveRecord instance into a Redis entry.
|
100
|
+
# Updates Redis entry if it already exists.
|
101
|
+
def redify_record(record)
|
102
|
+
key = Redify::Core.get_namespaced_key_name_for(:record => record)
|
103
|
+
record.class.redify_handler.hmset(key, record.attributes.to_a.flatten)
|
104
|
+
puts "[Redify] #{record.class}\##{record.id} redified"
|
105
|
+
return record
|
106
|
+
end
|
107
|
+
|
108
|
+
# Callbacks for Redified models
|
109
|
+
|
110
|
+
def after_create(record)
|
111
|
+
record.class.redify_handler.rpush record.class.redify_keys[:all], record.id
|
112
|
+
end
|
113
|
+
|
114
|
+
def after_save(record)
|
115
|
+
redify_record record
|
116
|
+
end
|
117
|
+
|
118
|
+
def after_destroy(record)
|
119
|
+
puts "after_destroy"
|
120
|
+
puts record.inspect
|
121
|
+
end
|
122
|
+
|
123
|
+
# Deletes all Redis keys under current namespace
|
124
|
+
def flush_keys(resource = nil)
|
125
|
+
namespace = Redify::Settings.namespace
|
126
|
+
redis = Redify::Settings.default_handler
|
127
|
+
pattern = "#{namespace}:"
|
128
|
+
pattern << "#{resource}" if resource
|
129
|
+
pattern << "*"
|
130
|
+
redis.keys(pattern).each do |key|
|
131
|
+
redis.del(key)
|
132
|
+
end
|
133
|
+
# namespace is also a key by itself
|
134
|
+
redis.del(namespace) unless resource
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
data/lib/redify/model.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Redify
|
2
|
+
module Model
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
attr_accessor :redify_keys
|
9
|
+
|
10
|
+
def redify_handler
|
11
|
+
@redify_handler || Redify::Settings.default_handler
|
12
|
+
end
|
13
|
+
attr_writer :redify_handler
|
14
|
+
|
15
|
+
def find (*args)
|
16
|
+
|
17
|
+
if args.size > 0 && args.last.is_a?(Hash)
|
18
|
+
# let ActiveRecord deal with queries with extended options, including :skip_redify
|
19
|
+
args.last.delete(:skip_redify)
|
20
|
+
return super(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
a = args.at(0)
|
24
|
+
return send(a) if a == :first || a == :last || a == :all
|
25
|
+
|
26
|
+
records = []
|
27
|
+
|
28
|
+
args.each do |id|
|
29
|
+
records << Redify::Core.fetch_record(:resource => self, :id => id)
|
30
|
+
end
|
31
|
+
|
32
|
+
args.size == 1 ? records.first : records
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def first (*args)
|
37
|
+
Redify::Core.fetch_records_by_edge(self, false, args.first)
|
38
|
+
end
|
39
|
+
|
40
|
+
def last (*args)
|
41
|
+
Redify::Core.fetch_records_by_edge(self, true, args.first)
|
42
|
+
end
|
43
|
+
|
44
|
+
def all (*args)
|
45
|
+
records = []
|
46
|
+
redify_handler.lrange(redify_keys[:all], 0, -1).each do |record_id|
|
47
|
+
records << Redify::Core.fetch_record(:resource => self, :id => record_id)
|
48
|
+
end
|
49
|
+
records
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Redify
|
2
|
+
|
3
|
+
class Settings
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
attr_accessor :always_redify_associations, :raise_redis_errors
|
8
|
+
attr_reader :namespace
|
9
|
+
|
10
|
+
def namespace=(value)
|
11
|
+
return @namespace if @namespace == value
|
12
|
+
# remoces old namespace install
|
13
|
+
Redify::Application.uninstall
|
14
|
+
@namespace = value
|
15
|
+
Redify::Application.install
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_default_options
|
19
|
+
# silently falls back to ActiveRecord when Redis is unavailable
|
20
|
+
raise_redis_errors = false
|
21
|
+
|
22
|
+
# only redify associations when specified
|
23
|
+
always_redify_associations = false
|
24
|
+
|
25
|
+
# default namespace
|
26
|
+
namespace = "Redify"
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_handler=(handler)
|
30
|
+
@default_handler = handler
|
31
|
+
Redify::Application.install
|
32
|
+
end
|
33
|
+
attr_reader :default_handler
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/pauloddr-public.pem
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDhTCCAm2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMRYwFAYDVQQDDA1wYW5h
|
3
|
+
LmVzcXVpdmVsMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
|
4
|
+
FgNjb20wHhcNMTMxMDE4MTc1MTQyWhcNMTQxMDE4MTc1MTQyWjBEMRYwFAYDVQQD
|
5
|
+
DA1wYW5hLmVzcXVpdmVsMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJ
|
6
|
+
k/IsZAEZFgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVfvUK
|
7
|
+
4fm49UsGoYQl9uzMR49I2sNCPvuP9sNTkQ0MoTqIRTWtMtDwTWwr1ecdyCEK7Yba
|
8
|
+
qW9veJ5wGKLHAE7Gblev3VpCl/JpLZ+RXjVZmYpb0tt77bumTd5GHNX8RS0VOggd
|
9
|
+
kVaaBdECCquIir7ZzfRQzBHA2Fu5aR3r83wbiYtUX5WKHanq8xlSTvngtCeOs71j
|
10
|
+
RLEg5a1+29iOtaOjyxKa7kzYvGpSOPmGtd/Fog8AQePUGO9H5R6gTKqSyfzH2Hv9
|
11
|
+
q39LxTdbDUFlkSEKARoUqQkJ5fggRRyVnybqwixve8uQl3Ic8TmhoJQqEnPyiN6Z
|
12
|
+
8yS2cVBCxzvepeIdAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAd
|
13
|
+
BgNVHQ4EFgQUS1qsU97VgO7r+8/fl12UubiKPYIwIgYDVR0RBBswGYEXcGFuYS5l
|
14
|
+
c3F1aXZlbEBnbWFpbC5jb20wIgYDVR0SBBswGYEXcGFuYS5lc3F1aXZlbEBnbWFp
|
15
|
+
bC5jb20wDQYJKoZIhvcNAQEFBQADggEBANKPXO84hY8Ih2SFZWrFhsd8MgbIP4ws
|
16
|
+
GgJSduxmFLZ5IEQ5Emo0kGqrjoAgaQZ/zn75thdGihFdiyAK7yWCK8UqfFjub3gn
|
17
|
+
T5HHcypkAlNArYKVGz+FV/P4kwivsW9zVdtprLR9RybA0NGQGWtIhSRk56zlSmXt
|
18
|
+
mfCnq1LJdUiawssF9DrsPoi4uJUbkBMuLpslLiT4zGKuzmgm6ZeTDF6YKzF9sGSM
|
19
|
+
25/9vufSQ+z5rRCRjBZ9k+8h3QPuCzQkfmmkUsA6HsX6Hnx9+bpFWp72u47wEQkk
|
20
|
+
wKGToyzSzsBlAE7/zMwjWxIVuIDaZQfAiJ7pU8rqWpw1PcUDrNfZW2g=
|
21
|
+
-----END CERTIFICATE-----
|
data/redify.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'redify/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "redify"
|
8
|
+
spec.version = Redify::VERSION
|
9
|
+
spec.authors = ["Paulo Procopiou"]
|
10
|
+
spec.email = ["pana.esquivel@gmail.com"]
|
11
|
+
spec.description = %q{Redis layer for ActiveRecord models}
|
12
|
+
spec.summary = %q{Adds a Redis layer to some ActiveRecord finders}
|
13
|
+
spec.homepage = "https://github.com/pauloddr/redify"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.cert_chain = ['pauloddr-public.pem']
|
17
|
+
spec.signing_key = File.expand_path("~/.gemcert/pauloddr-private.pem")
|
18
|
+
|
19
|
+
spec.files = `git ls-files`.split($/)
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "redis"
|
28
|
+
spec.add_development_dependency "sqlite3"
|
29
|
+
spec.add_development_dependency "simplecov"
|
30
|
+
|
31
|
+
spec.add_runtime_dependency "activesupport", "~> 3.0"
|
32
|
+
spec.add_runtime_dependency "activerecord", "~> 3.0"
|
33
|
+
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Redify::Core do
|
4
|
+
|
5
|
+
let (:record) { User.find 1, :skip_redify => true }
|
6
|
+
let (:namespace) { Redify::Settings.namespace }
|
7
|
+
|
8
|
+
describe '.get_namespaced_key_name_for' do
|
9
|
+
subject { lambda {|options| Redify::Core.get_namespaced_key_name_for(options) } }
|
10
|
+
it { expect(subject.call(:resource => User, :collection => "All")).to eq("#{namespace}:Users:All") }
|
11
|
+
it { expect(subject.call(:resource => User, :collection => "OtherStuff")).to eq("#{namespace}:Users:Collections:OtherStuff") }
|
12
|
+
it { expect(subject.call(:record => record)).to eq("#{namespace}:User:1") }
|
13
|
+
it { expect(subject.call(:resource => User, :id => 1)).to eq("#{namespace}:User:1") }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '.get_key_name_for' do
|
17
|
+
subject { lambda {|options| Redify::Core.get_key_name_for(options) } }
|
18
|
+
it { expect(subject.call(:resource => User, :collection => "All")).to eq("Users:All") }
|
19
|
+
it { expect(subject.call(:resource => User, :collection => "OtherStuff")).to eq("Users:Collections:OtherStuff") }
|
20
|
+
it { expect(subject.call(:record => record)).to eq("User:1") }
|
21
|
+
it { expect(subject.call(:resource => User, :id => 1)).to eq("User:1") }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '.get_key_name_for_collection' do
|
25
|
+
subject { lambda {|options| Redify::Core.get_key_name_for_collection(options) } }
|
26
|
+
it { expect(subject.call(:resource => User, :collection => "All")).to eq("Users:All") }
|
27
|
+
it { expect(subject.call(:resource => User, :collection => "OtherStuff")).to eq("Users:Collections:OtherStuff") }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.get_key_name_for_record' do
|
31
|
+
subject { lambda {|record| Redify::Core.get_key_name_for_record(record) } }
|
32
|
+
it { expect(subject.call(record)).to eq("User:1") }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.get_key_name_for_resource_and_id' do
|
36
|
+
subject { lambda {|options| Redify::Core.get_key_name_for_resource_and_id(options) } }
|
37
|
+
it { expect(subject.call(:resource => User, :id => 1)).to eq("User:1") }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/spec/redify_spec.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Redify do
|
4
|
+
|
5
|
+
it "includes itself properly" do
|
6
|
+
expect(User.respond_to?(:redify_handler)).to be_true
|
7
|
+
expect(Post.respond_to?(:redify_handler)).to be_true
|
8
|
+
expect(Dummy.respond_to?(:redify_handler)).to be_false
|
9
|
+
end
|
10
|
+
|
11
|
+
it "creates Redis keys upon model initialization" do
|
12
|
+
expect(User.redify_handler.exists(User.redify_keys[:all])).to be_true
|
13
|
+
expect(Post.redify_handler.exists(Post.redify_keys[:all])).to be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
require 'support/active_record'
|
5
|
+
require 'redify' # needs activerecord
|
6
|
+
require 'support/redis'
|
7
|
+
require 'support/models' # needs redify + redis
|
8
|
+
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
#config.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
+
#config.run_all_when_everything_filtered = true
|
13
|
+
#config.filter_run :focus
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
#config.order = 'random'
|
20
|
+
|
21
|
+
config.after(:suite) do
|
22
|
+
# clean up
|
23
|
+
Redify::Core.flush_keys
|
24
|
+
Redify::Application.uninstall
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection :adapter => "sqlite3", :database => ":memory:"
|
4
|
+
|
5
|
+
ActiveRecord::Migration.verbose = false
|
6
|
+
|
7
|
+
ActiveRecord::Migration.create_table :users do |t|
|
8
|
+
t.string :name
|
9
|
+
t.integer :post_count
|
10
|
+
t.datetime :created_at, :null => false
|
11
|
+
t.datetime :updated_at, :null => false
|
12
|
+
end
|
13
|
+
|
14
|
+
ActiveRecord::Migration.create_table :posts do |t|
|
15
|
+
t.integer :user_id
|
16
|
+
t.string :title
|
17
|
+
t.text :content
|
18
|
+
t.datetime :created_at, :null => false
|
19
|
+
t.datetime :updated_at, :null => false
|
20
|
+
end
|
21
|
+
|
22
|
+
# This table won't use Redify
|
23
|
+
ActiveRecord::Migration.create_table :dummies do |t|
|
24
|
+
t.string :name
|
25
|
+
t.integer :user_id
|
26
|
+
t.datetime :created_at, :null => false
|
27
|
+
t.datetime :updated_at, :null => false
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
redify
|
3
|
+
has_many :posts
|
4
|
+
end
|
5
|
+
|
6
|
+
class Post < ActiveRecord::Base
|
7
|
+
redify
|
8
|
+
belongs_to :user
|
9
|
+
end
|
10
|
+
|
11
|
+
class Dummy < ActiveRecord::Base
|
12
|
+
# no Redify for you
|
13
|
+
belongs_to :user
|
14
|
+
end
|
15
|
+
|
16
|
+
# Seeds
|
17
|
+
|
18
|
+
User.create(:name => "User 1").posts.create(:title => "Post by User 1")
|
19
|
+
User.create(:name => "User 2").posts.create(:title => "Post by User 2", :content => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam quis dolor magna. Donec tortor lectus, venenatis at rhoncus ut, condimentum non neque. Sed sit amet porta velit. Fusce porta augue nec sem tempor ornare. Curabitur eu tempus mi. Nunc venenatis laoreet risus, id malesuada erat vulputate at. In aliquet mi nisi, at ornare dolor venenatis eu.")
|
20
|
+
User.create(:name => "User 3")
|
21
|
+
User.create(:name => "User 4").posts.create(:title => "Post by User 4")
|
22
|
+
User.create(:name => "User 5")
|
23
|
+
|
24
|
+
Post.create(:title => "Another Post by User 1", :user_id => 1)
|
metadata
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Paulo Procopiou
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- !binary |-
|
12
|
+
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURoVENDQW0yZ0F3SUJB
|
13
|
+
Z0lCQVRBTkJna3Foa2lHOXcwQkFRVUZBREJFTVJZd0ZBWURWUVFEREExd1lX
|
14
|
+
NWgKTG1WemNYVnBkbVZzTVJVd0V3WUtDWkltaVpQeUxHUUJHUllGWjIxaGFX
|
15
|
+
d3hFekFSQmdvSmtpYUprL0lzWkFFWgpGZ05qYjIwd0hoY05NVE14TURFNE1U
|
16
|
+
YzFNVFF5V2hjTk1UUXhNREU0TVRjMU1UUXlXakJFTVJZd0ZBWURWUVFECkRB
|
17
|
+
MXdZVzVoTG1WemNYVnBkbVZzTVJVd0V3WUtDWkltaVpQeUxHUUJHUllGWjIx
|
18
|
+
aGFXd3hFekFSQmdvSmtpYUoKay9Jc1pBRVpGZ05qYjIwd2dnRWlNQTBHQ1Nx
|
19
|
+
R1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURWZnZVSwo0Zm00OVVz
|
20
|
+
R29ZUWw5dXpNUjQ5STJzTkNQdnVQOXNOVGtRME1vVHFJUlRXdE10RHdUV3dy
|
21
|
+
MWVjZHlDRUs3WWJhCnFXOXZlSjV3R0tMSEFFN0dibGV2M1ZwQ2wvSnBMWitS
|
22
|
+
WGpWWm1ZcGIwdHQ3N2J1bVRkNUdITlg4UlMwVk9nZ2QKa1ZhYUJkRUNDcXVJ
|
23
|
+
aXI3WnpmUlF6QkhBMkZ1NWFSM3I4M3diaVl0VVg1V0tIYW5xOHhsU1R2bmd0
|
24
|
+
Q2VPczcxagpSTEVnNWExKzI5aU90YU9qeXhLYTdrell2R3BTT1BtR3RkL0Zv
|
25
|
+
ZzhBUWVQVUdPOUg1UjZnVEtxU3lmekgySHY5CnEzOUx4VGRiRFVGbGtTRUtB
|
26
|
+
Um9VcVFrSjVmZ2dSUnlWbnlicXdpeHZlOHVRbDNJYzhUbWhvSlFxRW5QeWlO
|
27
|
+
NloKOHlTMmNWQkN4enZlcGVJZEFnTUJBQUdqZ1lFd2Z6QUpCZ05WSFJNRUFq
|
28
|
+
QUFNQXNHQTFVZER3UUVBd0lFc0RBZApCZ05WSFE0RUZnUVVTMXFzVTk3VmdP
|
29
|
+
N3IrOC9mbDEyVXViaUtQWUl3SWdZRFZSMFJCQnN3R1lFWGNHRnVZUzVsCmMz
|
30
|
+
RjFhWFpsYkVCbmJXRnBiQzVqYjIwd0lnWURWUjBTQkJzd0dZRVhjR0Z1WVM1
|
31
|
+
bGMzRjFhWFpsYkVCbmJXRnAKYkM1amIyMHdEUVlKS29aSWh2Y05BUUVGQlFB
|
32
|
+
RGdnRUJBTktQWE84NGhZOEloMlNGWldyRmhzZDhNZ2JJUDR3cwpHZ0pTZHV4
|
33
|
+
bUZMWjVJRVE1RW1vMGtHcXJqb0FnYVFaL3puNzV0aGRHaWhGZGl5QUs3eVdD
|
34
|
+
SzhVcWZGanViM2duClQ1SEhjeXBrQWxOQXJZS1ZHeitGVi9QNGt3aXZzVzl6
|
35
|
+
VmR0cHJMUjlSeWJBME5HUUdXdEloU1JrNTZ6bFNtWHQKbWZDbnExTEpkVWlh
|
36
|
+
d3NzRjlEcnNQb2k0dUpVYmtCTXVMcHNsTGlUNHpHS3V6bWdtNlplVERGNllL
|
37
|
+
ekY5c0dTTQoyNS85dnVmU1ErejVyUkNSakJaOWsrOGgzUVB1Q3pRa2ZtbWtV
|
38
|
+
c0E2SHNYNkhueDkrYnBGV3A3MnU0N3dFUWtrCndLR1RveXpTenNCbEFFNy96
|
39
|
+
TXdqV3hJVnVJRGFaUWZBaUo3cFU4cnFXcHcxUGNVRHJOZlpXMmc9Ci0tLS0t
|
40
|
+
RU5EIENFUlRJRklDQVRFLS0tLS0K
|
41
|
+
date: 2013-10-18 00:00:00.000000000 Z
|
42
|
+
dependencies:
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: bundler
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ~>
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.3'
|
50
|
+
type: :development
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '1.3'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: rake
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: rspec
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: redis
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: sqlite3
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: simplecov
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: activesupport
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '3.0'
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ~>
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '3.0'
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: activerecord
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ~>
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '3.0'
|
148
|
+
type: :runtime
|
149
|
+
prerelease: false
|
150
|
+
version_requirements: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ~>
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '3.0'
|
155
|
+
description: Redis layer for ActiveRecord models
|
156
|
+
email:
|
157
|
+
- pana.esquivel@gmail.com
|
158
|
+
executables: []
|
159
|
+
extensions: []
|
160
|
+
extra_rdoc_files: []
|
161
|
+
files:
|
162
|
+
- .gitignore
|
163
|
+
- .rspec
|
164
|
+
- Gemfile
|
165
|
+
- LICENSE.txt
|
166
|
+
- README.md
|
167
|
+
- Rakefile
|
168
|
+
- lib/redify.rb
|
169
|
+
- lib/redify/application.rb
|
170
|
+
- lib/redify/base.rb
|
171
|
+
- lib/redify/core.rb
|
172
|
+
- lib/redify/model.rb
|
173
|
+
- lib/redify/settings.rb
|
174
|
+
- lib/redify/version.rb
|
175
|
+
- pauloddr-public.pem
|
176
|
+
- redify.gemspec
|
177
|
+
- spec/redify/core_spec.rb
|
178
|
+
- spec/redify_spec.rb
|
179
|
+
- spec/spec_helper.rb
|
180
|
+
- spec/support/active_record.rb
|
181
|
+
- spec/support/models.rb
|
182
|
+
- spec/support/redis.rb
|
183
|
+
homepage: https://github.com/pauloddr/redify
|
184
|
+
licenses:
|
185
|
+
- MIT
|
186
|
+
metadata: {}
|
187
|
+
post_install_message:
|
188
|
+
rdoc_options: []
|
189
|
+
require_paths:
|
190
|
+
- lib
|
191
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
192
|
+
requirements:
|
193
|
+
- - ! '>='
|
194
|
+
- !ruby/object:Gem::Version
|
195
|
+
version: '0'
|
196
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ! '>='
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
requirements: []
|
202
|
+
rubyforge_project:
|
203
|
+
rubygems_version: 2.0.6
|
204
|
+
signing_key:
|
205
|
+
specification_version: 4
|
206
|
+
summary: Adds a Redis layer to some ActiveRecord finders
|
207
|
+
test_files:
|
208
|
+
- spec/redify/core_spec.rb
|
209
|
+
- spec/redify_spec.rb
|
210
|
+
- spec/spec_helper.rb
|
211
|
+
- spec/support/active_record.rb
|
212
|
+
- spec/support/models.rb
|
213
|
+
- spec/support/redis.rb
|
metadata.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
���2n�����4��٘0F�4Hy2*����w�pY�i�p�SWΌ�J��(鏗�2@Gz�+1iL]�4��o,G��g)Ι1�?�^�^tۂ^,���v�Ǿ�iH�gu]������Z�����X��?��%C�T������%�vq��4?���Ur� ��_LE|,r��8Yn�,$�\��IHh���.AIb��9�kvZ�&��(��41aq���=p:NJ���������?��r�i�U�+�۵f
|