redis-attrs 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.
@@ -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 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in redis-attrs.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Ernesto Garcia
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,146 @@
1
+ # Redis::Attrs - Add attributes to Ruby classes backed by Redis
2
+
3
+ This gem is an amalgamation of the ideas found within the [redis_props][redis_props]
4
+ and [redis-objects][redis-objects] gems, plus a few new ideas here and there. It
5
+ provides a way to define, on any Ruby class, some attributes that are backed by
6
+ [Redis][redis] behind the curtain.
7
+
8
+ Here are some of the characteristics that define this library:
9
+
10
+ - Easy to integrate directly with existing ORMs - ActiveRecord, DataMapper, etc.
11
+ - Not confined to ORMs. Use it in whatever Ruby classes you want.
12
+ - It does work better with ORMs because it requires each object to provide a
13
+ unique id identifying it, something already provided by most ORMs out of the box.
14
+ - Supports scalar value types, as well as more complex value types such as
15
+ collection types, counters and locks.
16
+ - Integers are returned as integers, rather than '17'. The same holds for dates,
17
+ times, floats, etc.
18
+ - Collection types can be assigned a Ruby-style collection to set their whole
19
+ content at once, resetting whatever content there was in the Redis key.
20
+ - The user can add support for more scalar data types with no built-in support.
21
+
22
+ ## Installation
23
+
24
+ Add this line to your application's Gemfile:
25
+
26
+ gem 'redis-attrs'
27
+
28
+ And then execute:
29
+
30
+ $ bundle
31
+
32
+ Or install it yourself as:
33
+
34
+ $ gem install redis-attrs
35
+
36
+ ## Usage
37
+
38
+ Start by defining some attributes on your class:
39
+
40
+ class Film
41
+ include Redis::Attrs
42
+ redis_attrs :title => :string, :length => :integer
43
+ redis_attrs :released_on => :date, :cast => :list
44
+
45
+ # Remember that the objects need an id for this to work
46
+ attr_reader :id
47
+ def initialize(id)
48
+ @id = id
49
+ end
50
+
51
+ def presentation_title
52
+ "#{title} (#{released_on.year})"
53
+ end
54
+ end
55
+
56
+ Then you can use those attributes as you would regularly, but internally they are
57
+ reading from and writing to Redis.
58
+
59
+ >> film = Film.new(3)
60
+ >> film.title = "Argo"
61
+ >> film.released_on = "2012-10-12"
62
+ >> puts film.presentation_title
63
+ Argo (2012)
64
+ >> puts film.cast.size
65
+ 0
66
+ >> film.cast = ["Ben Affleck", "Alan Arkin", "Brian Cranston"]
67
+ >> puts film.cast.size
68
+ 3
69
+ >> puts film.cast[-3]
70
+ Ben Affleck
71
+
72
+ `Redis::Attrs` will work on _any_ class that provides an `id` method that returns
73
+ a unique value. `Redis::Attrs` will automatically create keys that are unique to
74
+ each object, in the format:
75
+
76
+ class_name:id:attr_name
77
+
78
+ ### Supported types
79
+
80
+ `Redis::Attrs` supports the following scalar types: `string`, `integer`, `float`,
81
+ `boolean`, `date` and `time`. These are automatically serialized and deserialized
82
+ when written to and read from Redis.
83
+
84
+ In addition, the library also supports some collection types and a couple other
85
+ non-scalar types: `list`, `hash`, `set`, `sorted_set`, `counter` and `lock`. These
86
+ are all implemented using the [redis-objects][redis-objects] gem, each type handled
87
+ by a class that encapsulate all Redis logic around them.
88
+
89
+ ### Defining new scalar types
90
+
91
+ In addition to the predefined scalar types listed above, the user can define its
92
+ own scalar types, by subclassing `Redis::Attrs::Scalar` and defining how to serialize
93
+ and deserialize its values.
94
+
95
+ The following example defines a data-type that stores its values serialized as JSON.
96
+ The `serialize` and `deserialize` methods define how this process is done. After
97
+ registering the type with `Redis::Attrs`, a new attribute is added to the class
98
+ `Film` defined above.
99
+
100
+ class JSONScalar < Redis::Attrs::Scalar
101
+ def serialize(value)
102
+ value.to_json
103
+ end
104
+
105
+ def deserialize(value)
106
+ JSON.parse(value)
107
+ end
108
+ end
109
+
110
+ Redis::Attrs.register_type(:json, JSONScalar)
111
+
112
+ class Film
113
+ redis_attrs :director => :json
114
+ end
115
+
116
+ After the definitions above, more complex data structures could be stored as a single
117
+ scalar value, by being serialized as JSON.
118
+
119
+ >> film = Film.new(1)
120
+ >> film.director = { "first_name" => "Ben", "last_name" => "Affleck" }
121
+ >> puts Redis::Attrs.redis.get("film:1:director")
122
+ {"first_name":"Ben","last_name":"Affleck"}
123
+
124
+ ### Attribute configuration options
125
+
126
+ The complex attribute types support some configuration options, mostly specific to
127
+ each type. When an attribute needs to be configured with some of these options, then
128
+ it must be declared with the singular version of the method `redis_attrs`, like below:
129
+
130
+ redis_attr :crawl, :lock, :expiration => 15.minutes
131
+ redis_attr :cast, :list, :marshal => true
132
+
133
+ For more details about the supported configuration options for each of the complex
134
+ data types, please refer to the [redis-objects][redis-objects] gem.
135
+
136
+ ## Contributing
137
+
138
+ 1. Fork it
139
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
140
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
141
+ 4. Push to the branch (`git push origin my-new-feature`)
142
+ 5. Create new Pull Request
143
+
144
+ [redis]: http://redis.io
145
+ [redis_props]: http://github.com/obie/redis_props
146
+ [redis-objects]: http://github.com/nateware/redis-objects
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,92 @@
1
+ require "redis-attrs/version"
2
+ require "redis"
3
+ require "active_support/inflector"
4
+
5
+ class Redis
6
+ module Attrs
7
+ def self.redis
8
+ @redis ||= Redis.new
9
+ end
10
+
11
+ def self.redis=(r)
12
+ raise ArgumentError, "Redis Attrs: Invalid Redis instance" unless r.is_a?(Redis)
13
+ @redis = r
14
+ end
15
+
16
+ module ClassMethods
17
+ def redis
18
+ Redis::Attrs.redis
19
+ end
20
+
21
+ def redis_key_prefix
22
+ @redis_key_refix ||= ActiveSupport::Inflector.underscore(self.name)
23
+ end
24
+
25
+ def redis_attrs(attrs = nil)
26
+ @redis_attrs ||= []
27
+ return @redis_attrs if attrs.nil?
28
+ attrs.each do |name, type|
29
+ redis_attr name, type
30
+ end
31
+ end
32
+
33
+ def redis_attr(name, type, options = {})
34
+ @redis_attrs ||= []
35
+ klass = Redis::Attrs::supported_types[type]
36
+ raise ArgumentError, "Unknown Redis::Attr type #{type}" if klass.nil?
37
+ attr = klass.new(self, name, type, options)
38
+ @redis_attrs << attr
39
+ end
40
+ end
41
+
42
+ module InstanceMethods
43
+ def redis
44
+ Redis::Attrs.redis
45
+ end
46
+ end
47
+
48
+ def self.included(receiver)
49
+ receiver.extend(ClassMethods)
50
+ receiver.send(:include, InstanceMethods)
51
+ end
52
+
53
+ def self.supported_types
54
+ @supported_types ||= {
55
+ # Scalar types
56
+ string: Redis::Attrs::String,
57
+ boolean: Redis::Attrs::Boolean,
58
+ date: Redis::Attrs::Date,
59
+ time: Redis::Attrs::Time,
60
+ integer: Redis::Attrs::Integer,
61
+ float: Redis::Attrs::Float,
62
+
63
+ # Complex types
64
+ counter: Redis::Attrs::Complex,
65
+ lock: Redis::Attrs::Complex,
66
+ hash: Redis::Attrs::Hash,
67
+ list: Redis::Attrs::List,
68
+ set: Redis::Attrs::List,
69
+ sorted_set: Redis::Attrs::Hash,
70
+ }
71
+ end
72
+
73
+ def self.register_type(type, klass)
74
+ type = type.to_sym
75
+ raise ArgumentError, "Redis attr type #{type} is already defined" if supported_types.include?(type)
76
+ raise ArgumentError, "Class implementing new type #{type} must be a subclass of Redis::Attrs::Scalar" unless klass.ancestors.include?(Scalar)
77
+ @supported_types[type] = klass
78
+ end
79
+
80
+ autoload :Base, 'redis-attrs/base'
81
+ autoload :Scalar, 'redis-attrs/scalar'
82
+ autoload :String, 'redis-attrs/string'
83
+ autoload :Boolean, 'redis-attrs/boolean'
84
+ autoload :Date, 'redis-attrs/date'
85
+ autoload :Time, 'redis-attrs/time'
86
+ autoload :Integer, 'redis-attrs/integer'
87
+ autoload :Float, 'redis-attrs/float'
88
+ autoload :Complex, 'redis-attrs/complex'
89
+ autoload :List, 'redis-attrs/list'
90
+ autoload :Hash, 'redis-attrs/hash'
91
+ end
92
+ end
@@ -0,0 +1,20 @@
1
+ class Redis
2
+ module Attrs
3
+ class Base
4
+ attr_reader :klass, :name, :type, :options
5
+
6
+ def initialize(klass, name, type, options)
7
+ @klass, @name, @type, @options = klass, name, type, options
8
+ end
9
+
10
+ def redis
11
+ Redis::Attrs.redis
12
+ end
13
+
14
+ def redis_key(id)
15
+ raise "id attribute is required in order to properly store Redis attributes" if id.nil?
16
+ "#{klass.redis_key_prefix}:#{id}:#{name}"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ class Redis
2
+ module Attrs
3
+ class Boolean < Scalar
4
+ def deserialize(value)
5
+ value.nil? ? nil : %w(true yes).include?(value.downcase)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,47 @@
1
+ require "redis/hash_key"
2
+ require "redis/list"
3
+ require "redis/set"
4
+ require "redis/sorted_set"
5
+ require "redis/lock"
6
+ require "redis/counter"
7
+
8
+ class Redis
9
+ module Attrs
10
+ class Complex < Base
11
+
12
+ def initialize(klass, name, type, options)
13
+ super
14
+ attr = self
15
+ attr_class = self.class.redis_object_class[self.type]
16
+
17
+ # Define the getter
18
+ klass.send(:define_method, name) do
19
+ instance_variable_get("@#{name}") || begin
20
+ obj = attr_class.new attr.redis_key(id), redis, options
21
+ instance_variable_set("@#{name}", obj)
22
+ end
23
+ end
24
+
25
+ # TODO: Add support for collection setters
26
+ if self.respond_to?(:setter)
27
+ klass.send(:define_method, "#{name}=") do |value|
28
+ obj = send(name)
29
+ attr.setter(id, obj, value)
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.redis_object_class
35
+ @@redis_object_class ||= {
36
+ lock: Redis::Lock,
37
+ counter: Redis::Counter,
38
+ hash: Redis::HashKey,
39
+ list: Redis::List,
40
+ set: Redis::Set,
41
+ sorted_set: Redis::SortedSet,
42
+ }
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,9 @@
1
+ class Redis
2
+ module Attrs
3
+ class Date < Scalar
4
+ def deserialize(value)
5
+ value.nil? ? nil : ::Date.parse(value)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Redis
2
+ module Attrs
3
+ class Float < Scalar
4
+ def deserialize(value)
5
+ value.nil? ? nil : value.to_f
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ class Redis
2
+ module Attrs
3
+ class Hash < Complex
4
+ def setter(id, hash_object, new_hash)
5
+ redis.del redis_key(id)
6
+ new_hash.each { |key, value| hash_object[key] = value }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ class Redis
2
+ module Attrs
3
+ class Integer < Scalar
4
+ def deserialize(value)
5
+ value.nil? ? nil : value.to_i
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ class Redis
2
+ module Attrs
3
+ class List < Complex
4
+ def setter(id, list_object, new_list)
5
+ redis.del redis_key(id)
6
+ new_list.each { |item| list_object << item }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,38 @@
1
+ require "time"
2
+
3
+ class Redis
4
+ module Attrs
5
+ class Scalar < Base
6
+
7
+ def initialize(klass, name, type, options)
8
+ super
9
+ attr = self
10
+
11
+ # Define the getter
12
+ klass.send(:define_method, name) do
13
+ value = redis.get attr.redis_key(id)
14
+ value.nil? ? nil : attr.deserialize(value)
15
+ end
16
+
17
+ # Define the setter
18
+ klass.send(:define_method, "#{name}=") do |value|
19
+ if value.nil?
20
+ redis.del attr.redis_key(id)
21
+ else
22
+ value = attr.serialize(value)
23
+ redis.set attr.redis_key(id), value
24
+ end
25
+ end
26
+ end
27
+
28
+ def serialize(value)
29
+ value.to_s
30
+ end
31
+
32
+ def deserialize(value)
33
+ value
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,6 @@
1
+ class Redis
2
+ module Attrs
3
+ class String < Scalar
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ class Redis
2
+ module Attrs
3
+ class Time < Scalar
4
+ def deserialize(value)
5
+ value.nil? ? nil : ::Time.parse(value)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class Redis
2
+ module Attrs
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'redis-attrs/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "redis-attrs"
8
+ gem.version = Redis::Attrs::VERSION
9
+ gem.authors = ["Ernesto Garcia"]
10
+ gem.email = ["gnapse@gmail.com"]
11
+ gem.description = %q{A module that allows Ruby objects to define attributes backed by a Redis data store. Works with any class or ORM.}
12
+ gem.summary = %q{Add persistent object attributes backed by redis}
13
+ gem.homepage = "http://github.com/gnapse/redis-attrs"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency "rspec"
21
+ gem.add_dependency "redis"
22
+ gem.add_dependency "activesupport"
23
+ gem.add_dependency "redis-objects"
24
+ end
@@ -0,0 +1,172 @@
1
+ require "spec_helper"
2
+ require "json"
3
+
4
+ class Film
5
+ include Redis::Attrs
6
+ redis_attrs title: :string, released_on: :date, length: :integer
7
+ redis_attrs created_at: :time, rating: :float, featured: :boolean
8
+
9
+ def id
10
+ 1
11
+ end
12
+ end
13
+
14
+ class JSONScalar < Redis::Attrs::Scalar
15
+ def serialize(value)
16
+ value.to_json
17
+ end
18
+
19
+ def deserialize(value)
20
+ JSON.parse(value)
21
+ end
22
+ end
23
+
24
+ describe Redis::Attrs do
25
+ let(:redis) { Redis::Attrs.redis }
26
+ let(:film) { Film.new }
27
+
28
+ it "has a version number" do
29
+ Redis::Attrs::VERSION.should_not be_nil
30
+ end
31
+
32
+ context "when included in a class" do
33
+ it "makes the class respond to .redis_attrs" do
34
+ Film.should respond_to(:redis_attrs)
35
+ end
36
+
37
+ it "provides the class and its instances with a .redis interface" do
38
+ Film.should respond_to(:redis)
39
+ film.should respond_to(:redis)
40
+
41
+ Film.redis.should be_a(Redis)
42
+ Film.redis.should equal(film.redis)
43
+ end
44
+ end
45
+
46
+ describe ".redis_attrs" do
47
+ it "adds getters and setters for the attributes defined" do
48
+ %w(title released_on length created_at rating featured).each do |attr|
49
+ film.should respond_to(attr)
50
+ film.should respond_to("#{attr}=")
51
+ end
52
+ end
53
+
54
+ context "with no paremeters" do
55
+ it "returns a list of all Redis attributes defined for the class" do
56
+ Film.redis_attrs.should be_a(Array)
57
+ Film.redis_attrs.count.should == 6
58
+ Film.redis_attrs.map(&:name).should == [:title, :released_on, :length, :created_at, :rating, :featured]
59
+ Film.redis_attrs.map(&:type).should == [:string, :date, :integer, :time, :float, :boolean]
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "getters" do
65
+ let(:now) { Time.parse("2013-02-22 22:31:12 -0500") }
66
+
67
+ it "return nil by default" do
68
+ film.title.should be_nil
69
+ film.released_on.should be_nil
70
+ film.length.should be_nil
71
+ end
72
+
73
+ it "return whatever was last set with the corresponding setter" do
74
+ film.title = "Argo"
75
+ film.title.should == "Argo"
76
+ end
77
+
78
+ it "keep the original value type" do
79
+ film.released_on = Date.parse("2012-10-12")
80
+ film.released_on.should == Date.parse("2012-10-12")
81
+ film.created_at = now
82
+ film.created_at.should == now
83
+ film.length = 135
84
+ film.length.should == 135
85
+ film.rating = 8.2
86
+ film.rating.should == 8.2
87
+ film.featured = true
88
+ film.featured.should == true
89
+ end
90
+ end
91
+
92
+ describe "setters" do
93
+ it "set the corresponding key in Redis" do
94
+ film.title = "Argo"
95
+ redis.get("film:1:title").should == "Argo"
96
+
97
+ film.rating = 8.1
98
+ redis.get("film:1:rating").should == "8.1"
99
+ end
100
+
101
+ it "unset the key when being assigned nil" do
102
+ film.rating = 8.1
103
+ redis.keys.should include("film:1:rating")
104
+
105
+ film.rating = nil
106
+ redis.keys.should_not include("film:1:rating")
107
+ redis.get("film:1:rating").should be_nil
108
+ end
109
+ end
110
+
111
+ describe ".register_type" do
112
+ it "allows to define support for scalar value types not covered by the library" do
113
+ Redis::Attrs.register_type(:json, JSONScalar)
114
+ Film.redis_attrs director: :json
115
+ film.director = { first_name: "Ben", last_name: "Affleck" }
116
+ redis.keys.should include("film:1:director")
117
+ redis.get("film:1:director").should == { first_name: "Ben", last_name: "Affleck" }.to_json
118
+ film.director.should == { "first_name" => "Ben", "last_name" => "Affleck" }
119
+ end
120
+ end
121
+
122
+ describe "collection attributes" do
123
+ it "support lists" do
124
+ Film.redis_attrs cast: :list
125
+ film.cast.should be_empty
126
+ film.cast = ["Ben Affleck", "Alan Arkin", "John Goodman", "Ben Affleck"]
127
+ film.cast.size.should == 4
128
+ end
129
+
130
+ it "support hashes" do
131
+ Film.redis_attrs crew: :hash
132
+ film.crew.should be_empty
133
+ film.crew = { costume: "John Doe", makeup: "Jane Doe", camera: "James Doe" }
134
+ film.crew.size.should == 3
135
+ film.crew.keys.should == %w(costume makeup camera)
136
+ end
137
+
138
+ it "support sets" do
139
+ Film.redis_attrs producers: :set
140
+ film.producers.should be_empty
141
+ film.producers = ["Grant Heslov", "Ben Affleck", "George Clooney", "Ben Affleck"]
142
+ film.producers.size.should == 3
143
+ end
144
+
145
+ it "support sorted sets" do
146
+ Film.redis_attrs rankings: :sorted_set
147
+ film.rankings.should be_empty
148
+ film.rankings = { "oscars" => 3, "golden globe" => 1, "bafta" => 2 }
149
+ film.rankings.first.should == "golden globe"
150
+ film.rankings.last.should == "oscars"
151
+ film.rankings.members.should == ["golden globe", "bafta", "oscars"]
152
+ end
153
+
154
+ it "support counters" do
155
+ Film.redis_attrs awards_count: :counter
156
+ film.awards_count.value.should == 0
157
+ film.awards_count.incr
158
+ film.awards_count.value.should == 1
159
+ end
160
+
161
+ it "support locks" do
162
+ Film.redis_attrs playing: :lock
163
+ film.playing.lock { }
164
+ end
165
+
166
+ it "support specifying configuration options" do
167
+ require "active_support/core_ext/numeric/time"
168
+ Film.redis_attr :watching, :lock, :expiration => 3.hours
169
+ film.watching.options[:expiration].should == 3.hours
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,12 @@
1
+ require "redis-attrs"
2
+
3
+ Redis::Attrs.redis = Redis.new(db: 13)
4
+
5
+ RSpec.configure do |config|
6
+
7
+ # Clean up the database
8
+ config.before(:each) do
9
+ Redis::Attrs.redis.flushdb
10
+ end
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis-attrs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ernesto Garcia
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: redis
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: activesupport
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: redis-objects
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: A module that allows Ruby objects to define attributes backed by a Redis
79
+ data store. Works with any class or ORM.
80
+ email:
81
+ - gnapse@gmail.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - .rspec
88
+ - Gemfile
89
+ - LICENSE.txt
90
+ - README.md
91
+ - Rakefile
92
+ - lib/redis-attrs.rb
93
+ - lib/redis-attrs/base.rb
94
+ - lib/redis-attrs/boolean.rb
95
+ - lib/redis-attrs/complex.rb
96
+ - lib/redis-attrs/date.rb
97
+ - lib/redis-attrs/float.rb
98
+ - lib/redis-attrs/hash.rb
99
+ - lib/redis-attrs/integer.rb
100
+ - lib/redis-attrs/list.rb
101
+ - lib/redis-attrs/scalar.rb
102
+ - lib/redis-attrs/string.rb
103
+ - lib/redis-attrs/time.rb
104
+ - lib/redis-attrs/version.rb
105
+ - redis-attrs.gemspec
106
+ - spec/redis_attrs_spec.rb
107
+ - spec/spec_helper.rb
108
+ homepage: http://github.com/gnapse/redis-attrs
109
+ licenses: []
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 1.8.24
129
+ signing_key:
130
+ specification_version: 3
131
+ summary: Add persistent object attributes backed by redis
132
+ test_files:
133
+ - spec/redis_attrs_spec.rb
134
+ - spec/spec_helper.rb