redify 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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=
@@ -0,0 +1,2 @@
1
+ ]
2
+ Z�0�g<�
@@ -0,0 +1 @@
1
+ �~��eU��5pe\��&3��*ߔ��
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in redify.gemspec
4
+ gemspec
@@ -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.
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ task :default => :spec
7
+ task :test => :spec
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Redify
2
+ VERSION = "0.0.1"
3
+ end
@@ -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-----
@@ -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
@@ -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
@@ -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)
@@ -0,0 +1,4 @@
1
+ require 'redis'
2
+
3
+ Redify::Settings.default_handler = Redis.new
4
+ Redify::Settings.namespace = "RedifyTest_#{Time.now.to_i}"
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
@@ -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