redis_model 0.1.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +187 -0
  6. data/Rakefile +15 -0
  7. data/lib/redis_model/adapters/paperclip.rb +51 -0
  8. data/lib/redis_model/attribute.rb +124 -0
  9. data/lib/redis_model/base.rb +67 -0
  10. data/lib/redis_model/belonged_to.rb +27 -0
  11. data/lib/redis_model/class_attribute.rb +50 -0
  12. data/lib/redis_model/configurations.rb +15 -0
  13. data/lib/redis_model/helpers/sorted_set_paginator.rb +80 -0
  14. data/lib/redis_model/intersected.rb +17 -0
  15. data/lib/redis_model/schema.rb +114 -0
  16. data/lib/redis_model/types/base.rb +32 -0
  17. data/lib/redis_model/types/base_value.rb +26 -0
  18. data/lib/redis_model/types/counter.rb +25 -0
  19. data/lib/redis_model/types/float.rb +17 -0
  20. data/lib/redis_model/types/hash.rb +53 -0
  21. data/lib/redis_model/types/integer.rb +17 -0
  22. data/lib/redis_model/types/list.rb +40 -0
  23. data/lib/redis_model/types/set.rb +59 -0
  24. data/lib/redis_model/types/sorted_set.rb +184 -0
  25. data/lib/redis_model/types/string.rb +11 -0
  26. data/lib/redis_model/types/timestamp.rb +26 -0
  27. data/lib/redis_model/version.rb +3 -0
  28. data/lib/redis_model.rb +37 -0
  29. data/redis_model.gemspec +28 -0
  30. data/spec/redis_model/attribute_spec.rb +77 -0
  31. data/spec/redis_model/base_spec.rb +34 -0
  32. data/spec/redis_model/class_attribute_spec.rb +16 -0
  33. data/spec/redis_model/helpers/sorted_set_paginator_spec.rb +33 -0
  34. data/spec/redis_model/schema_spec.rb +118 -0
  35. data/spec/redis_model/types/base_spec.rb +28 -0
  36. data/spec/redis_model/types/counter_spec.rb +32 -0
  37. data/spec/redis_model/types/float_spec.rb +20 -0
  38. data/spec/redis_model/types/hash_spec.rb +55 -0
  39. data/spec/redis_model/types/integer_spec.rb +22 -0
  40. data/spec/redis_model/types/list_spec.rb +55 -0
  41. data/spec/redis_model/types/set_spec.rb +62 -0
  42. data/spec/redis_model/types/sorted_set_spec.rb +303 -0
  43. data/spec/redis_model/types/string_spec.rb +28 -0
  44. data/spec/redis_model/types/timestamp_spec.rb +22 -0
  45. data/spec/spec_helper.rb +13 -0
  46. data/spec/support/dynamic_class.rb +5 -0
  47. metadata +190 -0
@@ -0,0 +1,114 @@
1
+ module RedisModel
2
+ # Public: Schema information for RedisModel::Base-derived classes. It
3
+ # contains information required to manipulate Redis data including data type
4
+ # and key label.
5
+ class Schema
6
+ attr_reader :klass, :data_type, :data_type_module
7
+
8
+ # Public: Data type label and their corresponding module responsible for
9
+ # specified type.
10
+ DATA_TYPES = {
11
+ value: RedisModel::Types::Counter,
12
+ counter: RedisModel::Types::Counter,
13
+ list: RedisModel::Types::List,
14
+ sorted_set: RedisModel::Types::SortedSet,
15
+ float: RedisModel::Types::Float,
16
+ set: RedisModel::Types::Set,
17
+ hash: RedisModel::Types::Hash,
18
+ string: RedisModel::Types::String,
19
+ timestamp: RedisModel::Types::Timestamp,
20
+ integer: RedisModel::Types::Integer
21
+ }
22
+
23
+ # Public: Exception class indicating some class tried to initiate data_type
24
+ # when one of its direct ancestors already have initiated.
25
+ class DuplicateDefinition < StandardError ; end
26
+
27
+ # Public: Exception raised when invalid data_type label is provided.
28
+ class UnknownType < StandardError ; end
29
+
30
+ # Public: Global index of RedisModel::Schema objects.
31
+ #
32
+ # Returns the Hash of global schema index.
33
+ def self.collection
34
+ @collection ||= {}
35
+ end
36
+
37
+ # Public: Find schema information for specified class. It could be schema
38
+ # defined for one of ancestors of the class.
39
+ #
40
+ # klass - Class to find schema.
41
+ #
42
+ # Returns RedisModel::Schema object for given class, nil if it does not
43
+ # exist.
44
+ def self.find(klass)
45
+ collection[(klass.ancestors - klass.included_modules).detect do |parent_klass|
46
+ collection[parent_klass]
47
+ end]
48
+ end
49
+
50
+ # Public: Register schema for specified class.
51
+ #
52
+ # klass - Class to register schema.
53
+ # options - Additional options for schema.
54
+ # :data_type - Data type of Redis value.
55
+ #
56
+ # Returns the Module corresponding to data type of the class.
57
+ def self.register(klass, options = {})
58
+ raise DuplicateDefinition.new if find(klass)
59
+
60
+ (collection[klass] = new(options.merge(klass: klass))).data_type_module
61
+ end
62
+
63
+ # Public: Initializes a Schema.
64
+ #
65
+ # options - Options for schema.
66
+ # :klass - Class being specified for the schema.
67
+ # :data_type - Data type of Redis value.
68
+ #
69
+ # Returns newly initialized Schema object.
70
+ def initialize(options = {})
71
+ raise UnknownType.new unless DATA_TYPES[options[:data_type]]
72
+
73
+ @klass = options[:klass]
74
+ @data_type = options[:data_type]
75
+ @data_type_module = DATA_TYPES[@data_type]
76
+ end
77
+
78
+ # Public: Key label of Redis value associated with instance of classes
79
+ # inherit RedisModel::Base.
80
+ #
81
+ # object - Instance of RedisModel::Base-derived class.
82
+ #
83
+ # Returns String containing label for specified object.
84
+ def key_label(object)
85
+ [base_key_label, @custom_key_label_proc && @custom_key_label_proc.call(object)].compact.join(':')
86
+ end
87
+
88
+ # Public: Defines custom part of key label by passing a block having arity
89
+ # of 1 to this method.
90
+ #
91
+ # block - Block or proc that converts object into custom label string
92
+ #
93
+ # Examples:
94
+ #
95
+ # schema.custom_key_label do |object|
96
+ # object.id
97
+ # end
98
+ #
99
+ # Returns nothing.
100
+ def custom_key_label(&block)
101
+ @custom_key_label_proc = block
102
+ end
103
+
104
+ protected
105
+
106
+ # Internal: Retrieves string used for label for Redis value associated with
107
+ # the schema. Base label can be
108
+ #
109
+ # Returns String containing base label.
110
+ def base_key_label
111
+ @key_label_base ||= [RedisModel::Configurations.instance.app_name, RedisModel::Configurations.instance.environment, @klass.name.underscore].compact.join(':')
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,32 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Provides methods for Redis commands related to plain key
4
+ # operations and helpers.
5
+ module Base
6
+ # Public: Asserts existence of Redis key having the label using Redis
7
+ # command ExiSTS.
8
+ #
9
+ # Returns true if key exists, false otherwise.
10
+ def exists?
11
+ connection.exists(key_label)
12
+ end
13
+
14
+ # Public: Removes Redis value associated with the key using Redis command
15
+ # DEL.
16
+ #
17
+ # Returns 1 if key is deleted, 0 otherwise.
18
+ def del
19
+ connection.del(key_label)
20
+ end
21
+
22
+ alias_method :clear, :del
23
+
24
+ # Public: Helper method for global Redis connection.
25
+ #
26
+ # Returns global Redis connection object.
27
+ def connection
28
+ RedisModel::Base.connection
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Base methods for helper types based on basic key-value pairs.
4
+ module BaseValue
5
+ include RedisModel::Types::Base
6
+
7
+ # Public: Reads value of string stored in Redis using GET command.
8
+ #
9
+ # Returns String contained in Redis. nil if it does not exist.
10
+ def get
11
+ @cached_value ||= RedisModel::Base.connection.get(key_label)
12
+ end
13
+
14
+ # Public: Sets value of string stored in Redis using SEt command.
15
+ #
16
+ # value - Value to set.
17
+ #
18
+ # Returns String contained in Redis. nil if it does not exist.
19
+ def set(value, options = {})
20
+ @cached_value = nil
21
+
22
+ RedisModel::Base.connection.set(key_label, value, options)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Methods needed for counter data type.
4
+ module Counter
5
+ include RedisModel::Types::BaseValue
6
+
7
+ # Public: Atomically increments counter value using Redis command INCR or
8
+ # INCRBY.
9
+ #
10
+ # by - Amount to increment by (default: 1).
11
+ #
12
+ # Returns Integer value of counter after increment.
13
+ def incr(by = nil)
14
+ by ? connection.incrby(key_label, by) : connection.incr(key_label)
15
+ end
16
+
17
+ # Public: Retrieves Integer value of counter.
18
+ #
19
+ # Returns Integer value of counter.
20
+ def to_i
21
+ (get || 0).to_i
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Methods needed for Float data type.
4
+ module Float
5
+ include RedisModel::Types::BaseValue
6
+
7
+ # Public: Retrieves Float value stored in the key.
8
+ #
9
+ # Returns Float value stored in the key. nil if it does not exist.
10
+ def to_f
11
+ get && get.to_f
12
+ end
13
+
14
+ alias_method :to_value, :to_f
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,53 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Methods for hash type of key in Redis.
4
+ module Hash
5
+ include Base
6
+
7
+ # Public: Sets a key in Hash using Redis HSET command.
8
+ #
9
+ # key - Key to set.
10
+ # value - Value to set.
11
+ #
12
+ # Returns new value.
13
+ def []=(key, value)
14
+ result = connection.hset(key_label, key.to_s, value)
15
+
16
+ @cached_hash = nil
17
+
18
+ value
19
+ end
20
+
21
+ # Public: Retrieves a key in Hash using Redis HGET command.
22
+ #
23
+ # key - Key to retrieve.
24
+ #
25
+ # Returns retrieved value.
26
+ def [](key)
27
+ connection.hget(key_label, key.to_s)
28
+ end
29
+
30
+ # Public: Increments a key in Hash using Redis HINCRBY command.
31
+ #
32
+ # key - Key to increment.
33
+ # by - Amount for increment (default: 1)
34
+ #
35
+ # Returns incremented value.
36
+ def incr(key, by = 1)
37
+ result = connection.hincrby(key_label, key, by)
38
+
39
+ @cached_hash = nil
40
+
41
+ result.to_i
42
+ end
43
+
44
+ def to_hash
45
+ @cached_hash ||= connection.hgetall(key_label)
46
+ end
47
+
48
+ def keys
49
+ connection.hkeys(key_label)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,17 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Methods needed for Integer type.
4
+ module Integer
5
+ include RedisModel::Types::BaseValue
6
+
7
+ # Public: Retrieves value stored in Redis key as Integer.
8
+ #
9
+ # Returns Integer value stored in Redis key, nil if it does not exist.
10
+ def to_i
11
+ get && get.to_i
12
+ end
13
+
14
+ alias_method :to_value, :to_i
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,40 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Methods needed for List type.
4
+ module List
5
+ include RedisModel::Types::Base
6
+
7
+ # Public: Fetches elements in Redis list as Array using LRANGE command.
8
+ #
9
+ # Returns Array containing elements in the list.
10
+ def to_a
11
+ connection.lrange key_label, 0, -1
12
+ end
13
+
14
+ # Public: Retrieves length of Redis list using LLEN command.
15
+ #
16
+ # Returns Integer containing length of the list.
17
+ def count
18
+ connection.llen key_label
19
+ end
20
+
21
+ alias_method :length, :count
22
+
23
+ # Public: Retrieves a element in the list using LINDEX command.
24
+ #
25
+ # Returns String containing value of the specified element.
26
+ def [](index)
27
+ connection.lindex key_label, index
28
+ end
29
+
30
+ # Public: Pushes a element into the list using RPUSH command.
31
+ #
32
+ # Returns true.
33
+ def <<(value)
34
+ connection.rpush key_label, value
35
+ end
36
+
37
+ alias_method :push, :<<
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,59 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Methods needed for Set type.
4
+ module Set
5
+ include RedisModel::Types::Base
6
+
7
+ # Public: Fetches elements in Redis set as Array using SMEMBERS command.
8
+ #
9
+ # Returns Array containing elements in the set.
10
+ def to_a
11
+ connection.smembers key_label
12
+ end
13
+
14
+ # Public: Retrieves length of Redis set using SCARD command.
15
+ #
16
+ # Returns Integer containing cardinality of the set.
17
+ def count
18
+ connection.scard key_label
19
+ end
20
+
21
+ alias_method :length, :count
22
+
23
+ # Public: Pushes a element into the set using SADD command.
24
+ #
25
+ # Returns true.
26
+ def <<(value)
27
+ connection.sadd key_label, value
28
+ end
29
+
30
+ # Public: Removes a element from the set using SREM command.
31
+ #
32
+ # Returns true.
33
+ def remove(value)
34
+ connection.srem key_label, value
35
+ end
36
+
37
+ # Public: Picks a member among elements in the set using SRANDMEMBER
38
+ # command.
39
+ #
40
+ # count - Number of elements to pick.
41
+ #
42
+ # Returns Array containing elements in the set randomly selected.
43
+ def pick(count)
44
+ RedisModel::Base.connection.pipelined do
45
+ count.times do
46
+ connection.srandmember(key_label)
47
+ end
48
+ end
49
+ end
50
+
51
+ # Public: Asserts value is included in the set using SISMEMBER command.
52
+ #
53
+ # Returns true if value is included in the set, false otherwise.
54
+ def include?(value)
55
+ connection.sismember key_label, value.to_s
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,184 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Methods needed for Sorted Set type. Note that it assumes
4
+ # elements are sorted in descending order of score as default because the
5
+ # module is implemented for leaderboard feature. Future releases will
6
+ # revert this decision and will use default order of Redis.
7
+ module SortedSet
8
+ include RedisModel::Types::Base
9
+
10
+ # Public: Fetches elements in the sorted set as Array.
11
+ #
12
+ # Returns Array containing elements in the set.
13
+ def to_a
14
+ get_range('-inf', '+inf', include_boundaries: true)
15
+ end
16
+
17
+ # Public: Counts number of elements in (from, to) interval using ZCOUNT
18
+ # command.
19
+ #
20
+ # from - Beginning point of the interval.
21
+ # to - Ending point of the interval.
22
+ #
23
+ # Returns Integer containing number of elements in the interval.
24
+ def count_range(from, to)
25
+ connection.zcount(key_label, from, to)
26
+ end
27
+
28
+ # Public: Asserts value is included in the set.
29
+ #
30
+ # Returns true if value is included in the set, false otherwise.
31
+ def include?(value)
32
+ !!connection.zrank(key_label, value)
33
+ end
34
+
35
+ # Public: Retrieves elements in [from, to] index interval. Elements are
36
+ # arranged in descending order of score. ZREVRANGE command is used.
37
+ #
38
+ # from - Beginning point of the index interval.
39
+ # to - Ending point of the index interval.
40
+ # options - Additional options for retrieval.
41
+ # :withscores - If it is set to true, returned array
42
+ # contains values and corresponding scores
43
+ # of elements.
44
+ #
45
+ # Returns Integer containing number of elements in the interval.
46
+ def get_range_by_rank(from, to, options = {})
47
+ connection.zrevrange(key_label, from, to, options)
48
+ end
49
+
50
+ # Public: Retrieves elements in (from, to) index interval. Elements are
51
+ # arranged in ascending order of score. ZRANGE command is used.
52
+ #
53
+ # from - Beginning point of the index interval.
54
+ # to - Ending point of the index interval.
55
+ # options - Additional options for retrieval.
56
+ # :withscores - If it is set to true, returned array
57
+ # contains values and corresponding scores
58
+ # of elements.
59
+ #
60
+ # Returns Integer containing number of elements in the interval.
61
+ def get_range_by_reverse_rank(from, to, options = {})
62
+ connection.zrange(key_label, from, to, options)
63
+ end
64
+
65
+ # Public: Retrieves index of element in the sorted set. Elements are
66
+ # arranged in descending order of score. ZREVRANK command is used.
67
+ #
68
+ # from - Beginning point of the index interval.
69
+ # to - Ending point of the index interval.
70
+ # options - Additional options for retrieval.
71
+ # :withscores - If it is set to true, returned array
72
+ # contains values and corresponding scores
73
+ # of elements.
74
+ #
75
+ # Returns Integer containing number of elements in the interval.
76
+ def get_rank(key)
77
+ connection.zrevrank(key_label, key)
78
+ end
79
+
80
+ # Public: Retrieves score of element having specified value using ZSCORE
81
+ # command.
82
+ #
83
+ # value - Value of the element in concern.
84
+ #
85
+ # Returns score of element.
86
+ def score(value)
87
+ connection.zscore(key_label, value)
88
+ end
89
+
90
+ # Public: Retrieves length of Redis sorted set using ZCARD command.
91
+ #
92
+ # Returns Integer containing cardinality of the sorted set.
93
+ def count
94
+ connection.zcard(key_label)
95
+ end
96
+
97
+ alias_method :length, :count
98
+
99
+ # Public: Retrieves elements in the sorted set in (from, to) interval
100
+ # using ZREVRANGEBYSCORE command.
101
+ #
102
+ # from - Beginning point of the interval.
103
+ # to - Ending point of the interval.
104
+ # options - Additional options for retrieval.
105
+ # :include_boundaries - If it is set to true, elements on
106
+ # beginning/ending points are included.
107
+ # :withscores - If it is set to true, returned array
108
+ # contains values and corresponding scores
109
+ # of elements.
110
+ #
111
+ # Returns Array of element values or value/score pairs.
112
+ def get_range(from, to, options = {})
113
+ if options.delete(:include_boundaries)
114
+ connection.zrevrangebyscore(key_label, to, from, options)
115
+ else
116
+ connection.zrevrangebyscore(key_label, "(#{to}", "(#{from}", options)
117
+ end
118
+ end
119
+
120
+ # Public: Puts an element in sorted set using ZADD command.
121
+ #
122
+ # score - Score for the element.
123
+ # value - Value for the element.
124
+ #
125
+ # Returns true.
126
+ def put(score, value)
127
+ connection.zadd(key_label, score, value)
128
+ end
129
+
130
+ # Public: Removes an element from the sorted set using ZREM command.
131
+ #
132
+ # value - Value to remove.
133
+ #
134
+ # Returns true.
135
+ def remove(value)
136
+ connection.zrem(key_label, value)
137
+ end
138
+
139
+ # Public: Removes elements of the sorted set in specified interval using
140
+ # ZREMRANGEBYSCORE command.
141
+ #
142
+ # from - Beginning point of the interval (default: '-inf').
143
+ # to - Ending point of the interval (default: '+inf').
144
+ #
145
+ # Returns true.
146
+ def remove_range(from = '-inf', to = '+inf')
147
+ connection.zremrangebyscore(key_label, from, to)
148
+ end
149
+
150
+ # Public: Duplicates the sorted set with new key label using ZUNIONSTORE
151
+ # command.
152
+ #
153
+ # Returns true if duplication was successful, false otherwise.
154
+ def duplicate(new_key_label)
155
+ connection.zunionstore(new_key_label, [key_label]) if exists?
156
+ end
157
+
158
+ # Public: Generates intersected sorted set with another sorted set or set
159
+ # and perform operations on the new intersected set optionally.
160
+ #
161
+ # set - Another set to perform intersection with the sorted set.
162
+ # options - Additional options for the intersection.
163
+ # :seed - Seed for the new key label used to avoid naming
164
+ # confliction.
165
+ # block - An optional block that performs RedisModel commands with the
166
+ # intersected sorted set. If the block is given, intersected
167
+ # sorted set is removed after commands are completed.
168
+ #
169
+ # Returns RedisModel::Intersected object resulted from intersection if
170
+ # block was not given. If block was given, result of block is returned.
171
+ def intersect(set, options = {}, &block)
172
+ result = intersected = RedisModel::Intersected.new([self, set], options[:seed])
173
+
174
+ if block_given?
175
+ intersected.generate
176
+ result = yield(intersected)
177
+ intersected.clear
178
+ end
179
+
180
+ result
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,11 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Methods needed for string type.
4
+ module String
5
+ include RedisModel::Types::BaseValue
6
+
7
+ alias_method :to_s, :get
8
+ alias_method :to_value, :get
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ module RedisModel
2
+ module Types
3
+ # Internal: Methods needed for timestamp type.
4
+ module Timestamp
5
+ include RedisModel::Types::BaseValue
6
+
7
+ # Public: Reads value on Redis and converts it to timestamp.
8
+ #
9
+ # Returns Time object.
10
+ def to_time
11
+ Time.parse(get) rescue nil
12
+ end
13
+
14
+ alias_method :to_value, :to_time
15
+
16
+ # Public: Sets ISO 8601 string of timestamp to Redis.
17
+ #
18
+ # timestamp - Timestamp to store.
19
+ #
20
+ # Returns nothing.
21
+ def set(timestamp)
22
+ super(timestamp.utc.iso8601)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module RedisModel
2
+ VERSION = '0.1.0.pre3'
3
+ end
@@ -0,0 +1,37 @@
1
+ require 'singleton'
2
+ require 'time'
3
+
4
+ require 'redis'
5
+ require 'active_support/inflector'
6
+
7
+ require "redis_model/version"
8
+ require 'redis_model/configurations'
9
+ require 'redis_model/types/base'
10
+ require 'redis_model/types/base_value'
11
+ require 'redis_model/types/string'
12
+ require 'redis_model/types/counter'
13
+ require 'redis_model/types/list'
14
+ require 'redis_model/types/sorted_set'
15
+ require 'redis_model/types/float'
16
+ require 'redis_model/types/set'
17
+ require 'redis_model/types/hash'
18
+ require 'redis_model/types/timestamp'
19
+ require 'redis_model/types/integer'
20
+ require 'redis_model/schema'
21
+ require 'redis_model/base'
22
+ require 'redis_model/belonged_to'
23
+ require 'redis_model/attribute'
24
+ require 'redis_model/class_attribute'
25
+ require 'redis_model/intersected'
26
+
27
+ # Public: RedisModel provides various types of interfaces to handle values on
28
+ # Redis from applications, mostly with ORM including ActiveRecord. RedisModel
29
+ # is highly customizable and tries to avoid polluting name space of previously
30
+ # defined classes and modules.
31
+ module RedisModel
32
+ def self.config
33
+ (@configurations ||= RedisModel::Configurations.instance).tap do |configurations|
34
+ yield configurations if block_given?
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'redis_model/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'redis_model'
8
+ spec.version = RedisModel::VERSION
9
+ spec.authors = ['Inbeom Hwang']
10
+ spec.email = ['hwanginbeom@gmail.com']
11
+ spec.summary = %q{Interfaces for Redis values.}
12
+ spec.description = %q{RedisModel provides various types of interfaces to handle values on Redis}
13
+ spec.homepage = 'http://gitlab.ultracaption.net/inbeom/redis_model'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'redis'
22
+ spec.add_dependency 'activesupport'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.5'
25
+ spec.add_development_dependency 'rake'
26
+ spec.add_development_dependency 'rspec'
27
+ spec.add_development_dependency 'kaminari'
28
+ end