redis_model 0.1.0.pre3

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.
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