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 ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ spec/config/database.yml
6
+ *.log
7
+ *.sqlite3
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
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in redis-column.gemspec
4
+ gemspec
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"
@@ -0,0 +1,3 @@
1
+ module RedisColumn
2
+ VERSION = "0.0.1"
3
+ end
@@ -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,6 @@
1
+ class TestModel < ActiveRecord::Base; end
2
+
3
+ class DescriptionInRedisModel < TestModel
4
+ redis_col :description
5
+ end
6
+
@@ -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
@@ -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: []