redis-column 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README.md +28 -0
- data/Rakefile +1 -0
- data/lib/redis-column/version.rb +3 -0
- data/lib/redis-column.rb +92 -0
- data/redis-column.gemspec +25 -0
- data/spec/config/database.yml.sample +19 -0
- data/spec/config/models.rb +6 -0
- data/spec/config/schema.rb +12 -0
- data/spec/redis_column_spec.rb +69 -0
- data/spec/spec_helper.rb +66 -0
- metadata +127 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create 1.9.3@redis_column
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
RedisColumn
|
2
|
+
===========
|
3
|
+
|
4
|
+
Seamlessly extend your AR model with Redis
|
5
|
+
|
6
|
+
The RedisColumn gem allows for the seamless integration of Redis within your ActiveRecord model in order to store heavy objects away from tables with a lot of rows.
|
7
|
+
|
8
|
+
Installation
|
9
|
+
------------
|
10
|
+
|
11
|
+
gem install redis-column
|
12
|
+
|
13
|
+
Usage
|
14
|
+
-----
|
15
|
+
|
16
|
+
Within an initializer:
|
17
|
+
|
18
|
+
RedisColumn.config = YAML.load_file(Rails.root.join('config/redis.yml'))[:development]
|
19
|
+
|
20
|
+
|
21
|
+
Within your model:
|
22
|
+
|
23
|
+
class Page < ActiveRecord::Base
|
24
|
+
redis_column :body
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/redis-column.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require "active_record"
|
2
|
+
require "redis"
|
3
|
+
require File.dirname(__FILE__) + "/redis-column/version"
|
4
|
+
|
5
|
+
module RedisColumn
|
6
|
+
|
7
|
+
# Returns the current Redis configuration
|
8
|
+
def self.config
|
9
|
+
@@config ||= {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# Sets the Redis configuration
|
13
|
+
def self.config= hash
|
14
|
+
@@config = hash
|
15
|
+
end
|
16
|
+
|
17
|
+
# Active Redis connection
|
18
|
+
def self.redis_instance
|
19
|
+
@@redis_instance ||= Redis.new(config)
|
20
|
+
end
|
21
|
+
|
22
|
+
module Record
|
23
|
+
extend ActiveSupport::Concern
|
24
|
+
|
25
|
+
included do
|
26
|
+
# Set up the class attribute that must be available to all subclasses.
|
27
|
+
class_attribute :redis_columns
|
28
|
+
self.redis_columns = []
|
29
|
+
# Allow the instance access to this class attributes
|
30
|
+
delegate :redis_columns, :to => "self.class"
|
31
|
+
# Allow the instance access to RedisColumn.redis_instance
|
32
|
+
delegate :redis_instance, :to => "RedisColumn"
|
33
|
+
# Save the columns after
|
34
|
+
after_save :save_redis_columns!
|
35
|
+
# Boosh!
|
36
|
+
alias_method_chain :attributes, :redis_columns
|
37
|
+
end
|
38
|
+
|
39
|
+
module ClassMethods
|
40
|
+
|
41
|
+
# Setup a redis column
|
42
|
+
def redis_column column_name
|
43
|
+
self.redis_columns += [column_name]
|
44
|
+
attr_writer column_name
|
45
|
+
define_method column_name do # read the attribute or find from Redis and set to instance var
|
46
|
+
send(:instance_variable_get, "@#{column_name}") || send("#{column_name}=", read_redis_attribute(column_name))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
alias_method :redis_col, :redis_column
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
module InstanceMethods
|
54
|
+
|
55
|
+
# Returns the key to be used in Redis
|
56
|
+
def redis_key column_name
|
57
|
+
"#{self.class.model_name.i18n_key}:#{self.id}:#{column_name}"
|
58
|
+
end
|
59
|
+
|
60
|
+
# Read from Redis and unserialise
|
61
|
+
def read_redis_attribute column_name
|
62
|
+
val = redis_instance.get(redis_key(column_name))
|
63
|
+
YAML.load(val) unless val.nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
# Serialise and write to Redis
|
67
|
+
def write_redis_attribute column_name, val
|
68
|
+
redis_instance.set(redis_key(column_name), val.to_yaml) and return val
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns both the AR attributes and the Redis attributes in one hash
|
72
|
+
def attributes_with_redis_columns
|
73
|
+
_attributes = attributes_without_redis_columns.with_indifferent_access
|
74
|
+
redis_columns.inject(_attributes) do |res, column_name|
|
75
|
+
res.merge(column_name => send(column_name))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Save all values back to Redis
|
80
|
+
def save_redis_columns!
|
81
|
+
redis_columns.each do |column_name|
|
82
|
+
write_redis_attribute column_name, send(column_name)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
if defined?(ActiveRecord::Base)
|
91
|
+
ActiveRecord::Base.send :include, RedisColumn::Record
|
92
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "redis-column/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "redis-column"
|
7
|
+
s.version = RedisColumn::VERSION
|
8
|
+
s.authors = ["Alex Neill"]
|
9
|
+
s.email = ["alex.neill@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/ajn/redis-column"
|
11
|
+
s.summary = %q{Seamlessly extend your AR model with Redis}
|
12
|
+
s.description = %q{The RedisColumn gem allows for the seamless integration of Redis within your ActiveRecord model in order to store heavy objects away from tables with a lot of rows.}
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
s.add_dependency "activerecord"
|
19
|
+
s.add_dependency "redis"
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_development_dependency "autotest"
|
23
|
+
s.add_development_dependency "sqlite3"
|
24
|
+
s.add_development_dependency "fakeredis"
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
sqlite3:
|
2
|
+
adapter: sqlite3
|
3
|
+
database: redis_column.sqlite3
|
4
|
+
|
5
|
+
mysql:
|
6
|
+
adapter: mysql2
|
7
|
+
hostname: localhost
|
8
|
+
username: root
|
9
|
+
password:
|
10
|
+
database: redis_column
|
11
|
+
charset: utf8
|
12
|
+
|
13
|
+
postgresql:
|
14
|
+
adapter: postgresql
|
15
|
+
hostname: localhost
|
16
|
+
username: postgres
|
17
|
+
password:
|
18
|
+
database: redis_column
|
19
|
+
encoding: utf8
|
@@ -0,0 +1,12 @@
|
|
1
|
+
ActiveRecord::Schema.define :version => 0 do
|
2
|
+
create_table "test_models", :force => true do |t|
|
3
|
+
t.integer "integer"
|
4
|
+
t.datetime "created_at"
|
5
|
+
t.string "type", :default => 'TestModel'
|
6
|
+
t.string "string"
|
7
|
+
end
|
8
|
+
|
9
|
+
add_index "test_models", ["integer"], :name => "index_test_models_on_integer"
|
10
|
+
add_index "test_models", ["created_at"], :name => "index_test_models_on_created_at"
|
11
|
+
add_index "test_models", ["type"], :name => "index_test_models_on_type"
|
12
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TestModel do
|
4
|
+
it { TestModel.should respond_to(:redis_column) }
|
5
|
+
it { TestModel.should respond_to(:redis_col) }
|
6
|
+
it { TestModel.should respond_to(:redis_columns) }
|
7
|
+
|
8
|
+
describe 'redis_column' do
|
9
|
+
context 'with no arguments' do
|
10
|
+
it "should raise an argument error" do
|
11
|
+
lambda { TestModel.redis_column }.should raise_error(ArgumentError)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with a column_name" do
|
16
|
+
it "should add the column_name to the redis_columns array" do
|
17
|
+
TestModel.redis_columns.should == []
|
18
|
+
TestModel.redis_column :body
|
19
|
+
TestModel.redis_columns.should == [:body]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should add an accessor for the column_name" do
|
23
|
+
TestModel.redis_column :body
|
24
|
+
TestModel.new.should respond_to(:body)
|
25
|
+
TestModel.new.should respond_to(:body=)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe DescriptionInRedisModel do
|
32
|
+
it "should have a redis_column for the description attribute" do
|
33
|
+
DescriptionInRedisModel.redis_columns.should == [:description]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have a default redis key of '<model_name>:<id>:<column_name>' for the description attribute" do
|
37
|
+
instance = DescriptionInRedisModel.create
|
38
|
+
instance.redis_key(:description).should == "description_in_redis_model:#{instance.id}:description"
|
39
|
+
end
|
40
|
+
|
41
|
+
context "before save" do
|
42
|
+
it "should not have stored the description in redis" do
|
43
|
+
instance = DescriptionInRedisModel.new(description: "A looong description")
|
44
|
+
RedisColumn.redis_instance.get("description_in_redis_model:#{instance.id}:description").should_not be("A looong description".to_yaml)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when saving" do
|
49
|
+
it "should store the description in redis, with the key '<model_name>:<id>:<column_name>'" do
|
50
|
+
instance = DescriptionInRedisModel.create!(description: "A looong description")
|
51
|
+
RedisColumn.redis_instance.get("description_in_redis_model:#{instance.id}:description").should == "A looong description".to_yaml
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when saved" do
|
56
|
+
it "should retrive the description from redis, with the key '<model_name>:<id>:<column_name>'" do
|
57
|
+
instance = DescriptionInRedisModel.create!(description: "A looong description")
|
58
|
+
instance = DescriptionInRedisModel.find(instance.id)
|
59
|
+
instance.description.should == "A looong description"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return the redis_columns within :attributes" do
|
63
|
+
instance = DescriptionInRedisModel.create!(string: "A string", description: "A looong description")
|
64
|
+
instance.attributes.should have_key('string')
|
65
|
+
instance.attributes.should have_key('description')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
$LOAD_PATH << "." unless $LOAD_PATH.include?(".")
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require "rubygems"
|
6
|
+
require "bundler"
|
7
|
+
|
8
|
+
if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.5")
|
9
|
+
raise RuntimeError, "Your bundler version is too old." +
|
10
|
+
"Run `gem install bundler` to upgrade."
|
11
|
+
end
|
12
|
+
|
13
|
+
# Set up load paths for all bundled gems
|
14
|
+
Bundler.setup
|
15
|
+
rescue Bundler::GemNotFound
|
16
|
+
raise RuntimeError, "Bundler couldn't find some gems." +
|
17
|
+
"Did you run \`bundlee install\`?"
|
18
|
+
end
|
19
|
+
|
20
|
+
Bundler.require
|
21
|
+
require File.expand_path('../../lib/redis-column', __FILE__)
|
22
|
+
require "fakeredis"
|
23
|
+
db_name = ENV['DB'] || 'sqlite3'
|
24
|
+
database_yml = File.expand_path('../config/database.yml', __FILE__)
|
25
|
+
|
26
|
+
if File.exists?(database_yml)
|
27
|
+
active_record_configuration = YAML.load_file(database_yml)
|
28
|
+
|
29
|
+
ActiveRecord::Base.configurations = active_record_configuration
|
30
|
+
config = ActiveRecord::Base.configurations[db_name]
|
31
|
+
|
32
|
+
begin
|
33
|
+
ActiveRecord::Base.establish_connection(db_name)
|
34
|
+
ActiveRecord::Base.connection
|
35
|
+
rescue
|
36
|
+
case db_name
|
37
|
+
when /mysql/
|
38
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => nil))
|
39
|
+
ActiveRecord::Base.connection.create_database(config['database'], {:charset => 'utf8', :collation => 'utf8_unicode_ci'})
|
40
|
+
when 'postgresql'
|
41
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
42
|
+
ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => 'utf8'))
|
43
|
+
end
|
44
|
+
|
45
|
+
ActiveRecord::Base.establish_connection(config)
|
46
|
+
end
|
47
|
+
|
48
|
+
ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
|
49
|
+
ActiveRecord::Base.default_timezone = :utc
|
50
|
+
|
51
|
+
ActiveRecord::Base.silence do
|
52
|
+
ActiveRecord::Migration.verbose = false
|
53
|
+
|
54
|
+
load(File.dirname(__FILE__) + '/config/schema.rb')
|
55
|
+
load(File.dirname(__FILE__) + '/config/models.rb')
|
56
|
+
end
|
57
|
+
|
58
|
+
else
|
59
|
+
raise "Please create #{database_yml} first to configure your database. Take a look at: #{database_yml}.sample"
|
60
|
+
end
|
61
|
+
|
62
|
+
def clean_database!
|
63
|
+
ActiveRecord::Base.connection.execute "DELETE FROM test_models"
|
64
|
+
end
|
65
|
+
|
66
|
+
clean_database!
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redis-column
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alex Neill
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: &2152025520 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2152025520
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: redis
|
27
|
+
requirement: &2152025060 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2152025060
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &2152024300 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2152024300
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: autotest
|
49
|
+
requirement: &2152023600 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2152023600
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: sqlite3
|
60
|
+
requirement: &2152022840 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2152022840
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fakeredis
|
71
|
+
requirement: &2152022260 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *2152022260
|
80
|
+
description: The RedisColumn gem allows for the seamless integration of Redis within
|
81
|
+
your ActiveRecord model in order to store heavy objects away from tables with a
|
82
|
+
lot of rows.
|
83
|
+
email:
|
84
|
+
- alex.neill@gmail.com
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files: []
|
88
|
+
files:
|
89
|
+
- .gitignore
|
90
|
+
- .rspec
|
91
|
+
- .rvmrc
|
92
|
+
- Gemfile
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- lib/redis-column.rb
|
96
|
+
- lib/redis-column/version.rb
|
97
|
+
- redis-column.gemspec
|
98
|
+
- spec/config/database.yml.sample
|
99
|
+
- spec/config/models.rb
|
100
|
+
- spec/config/schema.rb
|
101
|
+
- spec/redis_column_spec.rb
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
homepage: https://github.com/ajn/redis-column
|
104
|
+
licenses: []
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
requirements: []
|
122
|
+
rubyforge_project:
|
123
|
+
rubygems_version: 1.8.10
|
124
|
+
signing_key:
|
125
|
+
specification_version: 3
|
126
|
+
summary: Seamlessly extend your AR model with Redis
|
127
|
+
test_files: []
|