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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +187 -0
- data/Rakefile +15 -0
- data/lib/redis_model/adapters/paperclip.rb +51 -0
- data/lib/redis_model/attribute.rb +124 -0
- data/lib/redis_model/base.rb +67 -0
- data/lib/redis_model/belonged_to.rb +27 -0
- data/lib/redis_model/class_attribute.rb +50 -0
- data/lib/redis_model/configurations.rb +15 -0
- data/lib/redis_model/helpers/sorted_set_paginator.rb +80 -0
- data/lib/redis_model/intersected.rb +17 -0
- data/lib/redis_model/schema.rb +114 -0
- data/lib/redis_model/types/base.rb +32 -0
- data/lib/redis_model/types/base_value.rb +26 -0
- data/lib/redis_model/types/counter.rb +25 -0
- data/lib/redis_model/types/float.rb +17 -0
- data/lib/redis_model/types/hash.rb +53 -0
- data/lib/redis_model/types/integer.rb +17 -0
- data/lib/redis_model/types/list.rb +40 -0
- data/lib/redis_model/types/set.rb +59 -0
- data/lib/redis_model/types/sorted_set.rb +184 -0
- data/lib/redis_model/types/string.rb +11 -0
- data/lib/redis_model/types/timestamp.rb +26 -0
- data/lib/redis_model/version.rb +3 -0
- data/lib/redis_model.rb +37 -0
- data/redis_model.gemspec +28 -0
- data/spec/redis_model/attribute_spec.rb +77 -0
- data/spec/redis_model/base_spec.rb +34 -0
- data/spec/redis_model/class_attribute_spec.rb +16 -0
- data/spec/redis_model/helpers/sorted_set_paginator_spec.rb +33 -0
- data/spec/redis_model/schema_spec.rb +118 -0
- data/spec/redis_model/types/base_spec.rb +28 -0
- data/spec/redis_model/types/counter_spec.rb +32 -0
- data/spec/redis_model/types/float_spec.rb +20 -0
- data/spec/redis_model/types/hash_spec.rb +55 -0
- data/spec/redis_model/types/integer_spec.rb +22 -0
- data/spec/redis_model/types/list_spec.rb +55 -0
- data/spec/redis_model/types/set_spec.rb +62 -0
- data/spec/redis_model/types/sorted_set_spec.rb +303 -0
- data/spec/redis_model/types/string_spec.rb +28 -0
- data/spec/redis_model/types/timestamp_spec.rb +22 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/dynamic_class.rb +5 -0
- 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,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
|
data/lib/redis_model.rb
ADDED
@@ -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
|
data/redis_model.gemspec
ADDED
@@ -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
|