redpear 0.6.4 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/redpear/connection.rb +110 -17
- data/lib/redpear/model/expiration.rb +18 -0
- data/lib/redpear/model/factory_girl.rb +27 -0
- data/lib/redpear/model/finders.rb +37 -0
- data/lib/redpear/model/machinist.rb +54 -0
- data/lib/redpear/model.rb +186 -63
- data/lib/redpear/schema/collection.rb +7 -7
- data/lib/redpear/{column.rb → schema/column.rb} +12 -6
- data/lib/redpear/schema/index.rb +22 -0
- data/lib/redpear/schema/score.rb +13 -0
- data/lib/redpear/schema.rb +9 -6
- data/lib/redpear/store/base.rb +120 -0
- data/lib/redpear/store/counter.rb +44 -0
- data/lib/redpear/store/enumerable.rb +8 -0
- data/lib/redpear/store/hash.rb +120 -0
- data/lib/redpear/store/list.rb +144 -0
- data/lib/redpear/store/lock.rb +108 -0
- data/lib/redpear/store/set.rb +147 -0
- data/lib/redpear/store/sorted_set.rb +239 -0
- data/lib/redpear/store/value.rb +66 -0
- data/lib/redpear/store.rb +11 -0
- data/lib/redpear.rb +7 -22
- metadata +45 -30
- data/lib/redpear/core_ext/stringify_keys.rb +0 -17
- data/lib/redpear/counters.rb +0 -26
- data/lib/redpear/expiration.rb +0 -27
- data/lib/redpear/finders.rb +0 -59
- data/lib/redpear/index.rb +0 -31
- data/lib/redpear/machinist.rb +0 -51
- data/lib/redpear/members.rb +0 -83
- data/lib/redpear/namespace.rb +0 -79
- data/lib/redpear/nest.rb +0 -100
- data/lib/redpear/persistence.rb +0 -147
- data/lib/redpear/zindex.rb +0 -26
- data/lib/redpear/zmembers.rb +0 -68
data/lib/redpear/expiration.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
module Redpear::Expiration
|
2
|
-
|
3
|
-
# Expires the record.
|
4
|
-
# @param [Time, Integer] either a Time or an Integer period (in seconds)
|
5
|
-
def expire(value)
|
6
|
-
return false unless persisted?
|
7
|
-
|
8
|
-
case value
|
9
|
-
when Time
|
10
|
-
nest.expireat(value.to_i)
|
11
|
-
when Integer
|
12
|
-
nest.expire(value)
|
13
|
-
when String
|
14
|
-
value = Kernel::Integer(value) rescue nil
|
15
|
-
expire(value)
|
16
|
-
else
|
17
|
-
false
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# @return [Integer] the period this record has to live.
|
22
|
-
# May return -1 for non-expiring records and nil for non-persisted records.
|
23
|
-
def ttl
|
24
|
-
nest.ttl if persisted?
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
data/lib/redpear/finders.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
module Redpear::Finders
|
2
|
-
extend Redpear::Concern
|
3
|
-
|
4
|
-
module ClassMethods
|
5
|
-
|
6
|
-
# @return [Array] the IDs of all existing records
|
7
|
-
def members
|
8
|
-
Redpear::Members.new(mb_nest)
|
9
|
-
end
|
10
|
-
|
11
|
-
# @return [Integer] the number of total records
|
12
|
-
def count
|
13
|
-
members.count
|
14
|
-
end
|
15
|
-
|
16
|
-
# @return [Array] all records
|
17
|
-
def all
|
18
|
-
members.map {|id| find(id) }.compact
|
19
|
-
end
|
20
|
-
|
21
|
-
# @yield [Model] applies a block to each object
|
22
|
-
def find_each(&block)
|
23
|
-
members.each do |id|
|
24
|
-
record = find(id)
|
25
|
-
yield(record) if record
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# Finds a single record.
|
30
|
-
#
|
31
|
-
# @param id the ID of the record to retrieve
|
32
|
-
# @param [Hash] options additional options
|
33
|
-
# @option :lazy defaults to true, set to false to load the record instantly
|
34
|
-
# @return [Redpear::Model] a record, or nil when not found
|
35
|
-
def find(id, options = {})
|
36
|
-
record = instantiate('id' => id.to_s) # Initialize
|
37
|
-
if record.nest.exists # Do we have a record key?
|
38
|
-
record.refresh_attributes if options[:lazy] == false
|
39
|
-
record
|
40
|
-
else # Must be an expired or orphaned one
|
41
|
-
record.destroy # Destroy (removes from mb_nest set)
|
42
|
-
nil
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# @param id the ID to check
|
47
|
-
# @return [Boolean] true or false
|
48
|
-
def exists?(id)
|
49
|
-
members.include?(id)
|
50
|
-
end
|
51
|
-
|
52
|
-
def instantiate(*a)
|
53
|
-
new(*a).tap do |instance|
|
54
|
-
instance.send :instance_variable_set, :@__loaded__, false
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
data/lib/redpear/index.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
class Redpear::Index < Redpear::Column
|
2
|
-
|
3
|
-
# @return [Redpear::Nest] the namespace of the index. Example:
|
4
|
-
#
|
5
|
-
# index = Comment.columns.lookup["post_id"]
|
6
|
-
# index.namespace # => "comments:[post_id]"
|
7
|
-
#
|
8
|
-
def namespace
|
9
|
-
model.namespace["[#{to_s}]"]
|
10
|
-
end
|
11
|
-
|
12
|
-
# @param [String] value the index value
|
13
|
-
# @return [Redpear::Nest] the nest for a specific value. Example:
|
14
|
-
#
|
15
|
-
# index = Comment.columns.lookup["post_id"]
|
16
|
-
# index.nest(123) # => "comments:[post_id]:123"
|
17
|
-
# index.nest(nil) # => "comments:[post_id]:_"
|
18
|
-
# index.nest("") # => "comments:[post_id]:_"
|
19
|
-
#
|
20
|
-
def nest(value)
|
21
|
-
value = "_" if value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
22
|
-
namespace[value]
|
23
|
-
end
|
24
|
-
|
25
|
-
# @param [String] value the index value
|
26
|
-
# @return [Array] the IDs of all existing records for a given index value
|
27
|
-
def members(value)
|
28
|
-
Redpear::Members.new nest(value)
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
data/lib/redpear/machinist.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'redpear'
|
2
|
-
require 'machinist'
|
3
|
-
|
4
|
-
# Machinist module for your tests/specs. Example:
|
5
|
-
#
|
6
|
-
# # spec/support/blueprints.rb
|
7
|
-
# require "redpear/machinist"
|
8
|
-
#
|
9
|
-
# Post.blueprint do
|
10
|
-
# title { "A Title" }
|
11
|
-
# created_at { 2.days.ago }
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
module Redpear::Machinist
|
15
|
-
|
16
|
-
class Blueprint < Machinist::Blueprint
|
17
|
-
|
18
|
-
def make!(attributes = {})
|
19
|
-
make(attributes).tap &:save
|
20
|
-
end
|
21
|
-
|
22
|
-
def lathe_class #:nodoc:
|
23
|
-
Lathe
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
class Lathe < Machinist::Lathe
|
29
|
-
protected
|
30
|
-
|
31
|
-
def make_one_value(attribute, args)
|
32
|
-
return unless block_given?
|
33
|
-
raise_argument_error(attribute) unless args.empty?
|
34
|
-
yield
|
35
|
-
end
|
36
|
-
|
37
|
-
def assign_attribute(key, value) #:nodoc:
|
38
|
-
@assigned_attributes[key.to_sym] = value
|
39
|
-
@object.load key => value
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
class Redpear::Model #:nodoc:
|
46
|
-
extend Machinist::Machinable
|
47
|
-
|
48
|
-
def self.blueprint_class
|
49
|
-
Redpear::Machinist::Blueprint
|
50
|
-
end
|
51
|
-
end
|
data/lib/redpear/members.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
class Redpear::Members
|
2
|
-
include Enumerable
|
3
|
-
|
4
|
-
attr_reader :nest
|
5
|
-
|
6
|
-
# Constructor
|
7
|
-
# @param [Redpear::Nest] nest
|
8
|
-
# the nest object
|
9
|
-
def initialize(nest)
|
10
|
-
@nest = nest
|
11
|
-
end
|
12
|
-
|
13
|
-
# @return [Boolean] true if member have been loaded
|
14
|
-
def loaded?
|
15
|
-
!@members.nil?
|
16
|
-
end
|
17
|
-
|
18
|
-
# @yield [String] do something with each member
|
19
|
-
def each(&block)
|
20
|
-
members.each(&block)
|
21
|
-
end
|
22
|
-
|
23
|
-
# @param [String] value
|
24
|
-
# check if this value is a member
|
25
|
-
# @return [Boolean] true if members contain the value
|
26
|
-
def include?(value)
|
27
|
-
loaded? ? @members.include?(value.to_s) : is_member?(value)
|
28
|
-
end
|
29
|
-
|
30
|
-
# @return [Set] the actual members
|
31
|
-
def members
|
32
|
-
@members ||= nest.smembers.to_set
|
33
|
-
end
|
34
|
-
|
35
|
-
# @return [Integer] then count of members
|
36
|
-
def count
|
37
|
-
@count ||= loaded? ? @members.size : cardinality
|
38
|
-
end
|
39
|
-
alias_method :size, :count
|
40
|
-
|
41
|
-
# Compares members
|
42
|
-
# @param [Object] other the object to compare with
|
43
|
-
# @return [Boolean] true if same as other
|
44
|
-
def ==(other)
|
45
|
-
case other
|
46
|
-
when Redpear::Members
|
47
|
-
other.members == members
|
48
|
-
when Set
|
49
|
-
other == members
|
50
|
-
when Array
|
51
|
-
other.to_set == members
|
52
|
-
else
|
53
|
-
super
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Is the value a member? This method is not cached, try using #include? instead.
|
58
|
-
# @param [String] value
|
59
|
-
def is_member?(value)
|
60
|
-
nest.sismember(value)
|
61
|
-
end
|
62
|
-
|
63
|
-
# @return [Integer] the cardinaliry of this set.
|
64
|
-
# This method is not cached, try using #count instead.
|
65
|
-
def cardinality
|
66
|
-
nest.scard
|
67
|
-
end
|
68
|
-
|
69
|
-
# Add a member to this set
|
70
|
-
# @param [Model] record
|
71
|
-
def add(record)
|
72
|
-
@members << record.id if loaded?
|
73
|
-
nest.sadd(record.id)
|
74
|
-
end
|
75
|
-
|
76
|
-
# Remove a member from this set
|
77
|
-
# @param [Model] record
|
78
|
-
def remove(record)
|
79
|
-
@members.delete(record.id) if loaded?
|
80
|
-
nest.srem(record.id)
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
data/lib/redpear/namespace.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
# Namespace organization for models. Example:
|
2
|
-
#
|
3
|
-
# class Comment < Model
|
4
|
-
# index :post_id
|
5
|
-
# end
|
6
|
-
# instance = Comment.save(:post_id => 2)
|
7
|
-
#
|
8
|
-
# Comment.namespace.keys
|
9
|
-
# # => ['comments:1', 'comments:+', 'comments:*', 'comments:post_id:2']
|
10
|
-
#
|
11
|
-
# # Instance nesting
|
12
|
-
# instance.nest # => 'comments:1'
|
13
|
-
# instance.nest.hgetall # => { "post_id" => "2" }
|
14
|
-
#
|
15
|
-
# # Member nesting
|
16
|
-
# Comment.mb_nest # "comments:[~]"
|
17
|
-
# Comment.mb_nest.smembers # => #<Set: {1}>
|
18
|
-
#
|
19
|
-
# # PK nesting
|
20
|
-
# Comment.pk_nest # "comments:[+]"
|
21
|
-
# Comment.pk_nest.get # 1 = last ID
|
22
|
-
#
|
23
|
-
# # Index nesting
|
24
|
-
# Comment.columns["post_id"].nest(2) # "comments:post_id:2"
|
25
|
-
# Comment.columns["post_id"].nest(2).smembers # #<Set: {1}>
|
26
|
-
#
|
27
|
-
module Redpear::Namespace
|
28
|
-
extend Redpear::Concern
|
29
|
-
|
30
|
-
module ClassMethods
|
31
|
-
|
32
|
-
# @return [Redpear::Nest] the namespace of this model, Example:
|
33
|
-
#
|
34
|
-
# Comment.namespace # => "comments":Redpear::Nest
|
35
|
-
#
|
36
|
-
def namespace
|
37
|
-
@namespace ||= Redpear::Nest.new(scope, master_connection, slave_connection)
|
38
|
-
end
|
39
|
-
|
40
|
-
# @return [String] the scope of this model. Example:
|
41
|
-
#
|
42
|
-
# Comment.scope # => "comments"
|
43
|
-
#
|
44
|
-
# Override if you want to use a differnet scope schema.
|
45
|
-
def scope
|
46
|
-
@scope ||= "#{name.split('::').last.downcase}s"
|
47
|
-
end
|
48
|
-
|
49
|
-
# @return [Redpear::Nest] the nest for the members store. Example:
|
50
|
-
#
|
51
|
-
# Comment.mb_nest # => 'comments:*'
|
52
|
-
# Comment.mb_nest.smembers # => [1, 2, 3]
|
53
|
-
#
|
54
|
-
def mb_nest
|
55
|
-
@mb_nest ||= namespace["[~]"]
|
56
|
-
end
|
57
|
-
|
58
|
-
# @return [Redpear::Nest] the nest for the primary-key incrementor. Example:
|
59
|
-
#
|
60
|
-
# Comment.pk_nest # => 'comments:+'
|
61
|
-
# Comment.pk_nest.get # => 0
|
62
|
-
# Comment.pk_nest.incr # => 1
|
63
|
-
#
|
64
|
-
def pk_nest
|
65
|
-
@pk_nest ||= namespace["[+]"]
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
# @return [Redpear::Nest] the nest for the current record. Example:
|
71
|
-
#
|
72
|
-
# comment.nest # => 'comments:123'
|
73
|
-
# Comment.new.nest # => 'comments:_'
|
74
|
-
#
|
75
|
-
def nest
|
76
|
-
self.class.namespace[id || '_']
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
data/lib/redpear/nest.rb
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
# Nested redis key-value store, with master slave support
|
2
|
-
# Heavily "inspired" by the nest library
|
3
|
-
# Original copyright: Michel Martens & Damian Janowski
|
4
|
-
class Redpear::Nest < ::String
|
5
|
-
|
6
|
-
MASTER_METHODS = %w|
|
7
|
-
append auth
|
8
|
-
bgrewriteaof bgsave blpop brpop brpoplpush
|
9
|
-
config
|
10
|
-
decr decrby del discard
|
11
|
-
exec expire expireat
|
12
|
-
flushall flushdb getset
|
13
|
-
hset hsetnx hincrby hmset hdel
|
14
|
-
incr incrby
|
15
|
-
linsert lpop lpush lpushx lrem lset ltrim
|
16
|
-
mapped_hmset mapped_mset mapped_msetnx
|
17
|
-
move mset msetnx multi
|
18
|
-
persist pipelined psubscribe punsubscribe quit
|
19
|
-
rename renamenx rpop rpoplpush rpush rpushx
|
20
|
-
sadd save sdiffstore set setbit
|
21
|
-
setex setnx setrange sinterstore
|
22
|
-
shutdown smove spop srem subscribe
|
23
|
-
sunionstore sync synchronize
|
24
|
-
unsubscribe unwatch watch
|
25
|
-
zadd zincrby zinterstore zrem
|
26
|
-
zremrangebyrank zremrangebyscore zunionstore
|
27
|
-
|.freeze
|
28
|
-
|
29
|
-
SLAVE_METHODS = %w|
|
30
|
-
dbsize debug get getbit getrange
|
31
|
-
echo exists
|
32
|
-
hget hmget hexists hlen hkeys hvals hgetall
|
33
|
-
info keys lastsave lindex llen lrange
|
34
|
-
mapped_hmget mapped_mget mget monitor
|
35
|
-
object ping publish randomkey
|
36
|
-
scard sdiff select sinter sismember slaveof
|
37
|
-
smembers sort srandmember strlen substr sunion
|
38
|
-
ttl type
|
39
|
-
zcard zcount zrange zrangebyscore zrank
|
40
|
-
zrevrange zrevrangebyscore zrevrank zscore
|
41
|
-
|.freeze
|
42
|
-
|
43
|
-
attr_reader :master, :slave, :current
|
44
|
-
|
45
|
-
# Constructor
|
46
|
-
# @param [String] key
|
47
|
-
# The redis key
|
48
|
-
# @param [Redis::Client|Redis::Namespace|ConnectionPool] master
|
49
|
-
# The master connection, optional, defaults to the current connection
|
50
|
-
# @param [Redis::Client|Redis::Namespace|ConnectionPool] slave
|
51
|
-
# The slave connection, optional, defaults to master
|
52
|
-
def initialize(key, master = Redis.current, slave = nil)
|
53
|
-
super(key)
|
54
|
-
@master = master
|
55
|
-
@slave = slave || master
|
56
|
-
end
|
57
|
-
|
58
|
-
# @param [multiple] keys
|
59
|
-
# Nest within these keys
|
60
|
-
# @return [Redpear::Nest]
|
61
|
-
# The nested key
|
62
|
-
def [](*keys)
|
63
|
-
self.class.new [self, *keys].join(':'), master, slave
|
64
|
-
end
|
65
|
-
|
66
|
-
# @param [Symbol] name
|
67
|
-
# Either :master or :slave
|
68
|
-
# @yield
|
69
|
-
# Perform a block with the given connection
|
70
|
-
def with_connection(name)
|
71
|
-
@current = send(name)
|
72
|
-
yield
|
73
|
-
ensure
|
74
|
-
@current = nil
|
75
|
-
end
|
76
|
-
alias_method :with, :with_connection
|
77
|
-
|
78
|
-
MASTER_METHODS.each do |meth|
|
79
|
-
define_method(meth) do |*args, &block|
|
80
|
-
client = current || master
|
81
|
-
if Redis.instance_method(meth).arity.zero?
|
82
|
-
client.send(meth, &block)
|
83
|
-
else
|
84
|
-
client.send(meth, self, *args, &block)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
SLAVE_METHODS.each do |meth|
|
90
|
-
define_method(meth) do |*args, &block|
|
91
|
-
client = current || slave
|
92
|
-
if Redis.instance_method(meth).arity.zero?
|
93
|
-
client.send(meth, &block)
|
94
|
-
else
|
95
|
-
client.send(meth, self, *args, &block)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
end
|
data/lib/redpear/persistence.rb
DELETED
@@ -1,147 +0,0 @@
|
|
1
|
-
# Redpear's persistence methods
|
2
|
-
module Redpear::Persistence
|
3
|
-
extend Redpear::Concern
|
4
|
-
|
5
|
-
module ClassMethods
|
6
|
-
|
7
|
-
# Runs a bulk-operation.
|
8
|
-
# @yield [] operations that should be run in the transaction
|
9
|
-
def transaction(&block)
|
10
|
-
namespace.multi(&block)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Create or update a record. Example:
|
14
|
-
#
|
15
|
-
# Post.save :body => "Hello World!" # => creates a new Post
|
16
|
-
# Post.save :id => 3, :body => "Hello World!" # => updates an existing Post
|
17
|
-
#
|
18
|
-
def save(*args)
|
19
|
-
new(*args).tap(&:save)
|
20
|
-
end
|
21
|
-
alias_method :save!, :save
|
22
|
-
|
23
|
-
# Destroys a record. Example:
|
24
|
-
# @param id the ID of the record to destroy
|
25
|
-
# @return [Redpear::Model] the destroyed record
|
26
|
-
def destroy(id)
|
27
|
-
new('id' => id).tap(&:destroy)
|
28
|
-
end
|
29
|
-
|
30
|
-
# Generates the next ID
|
31
|
-
def next_id
|
32
|
-
pk_nest.incr.to_s
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
# Returns true for new records
|
38
|
-
def new_record?
|
39
|
-
!id
|
40
|
-
end
|
41
|
-
|
42
|
-
# Returns true for existing records
|
43
|
-
def persisted?
|
44
|
-
!new_record?
|
45
|
-
end
|
46
|
-
|
47
|
-
# Reloads the record (destructive)
|
48
|
-
def reload
|
49
|
-
replace self.class.find(id, :lazy => false) if persisted?
|
50
|
-
self
|
51
|
-
end
|
52
|
-
|
53
|
-
# Load attributes from DB (destructive)
|
54
|
-
def refresh_attributes
|
55
|
-
update nest.hgetall if persisted?
|
56
|
-
@__loaded__ = true
|
57
|
-
self
|
58
|
-
end
|
59
|
-
|
60
|
-
# Saves the record.
|
61
|
-
#
|
62
|
-
# @param [Hash] options additional options
|
63
|
-
# @option options [Integer|Date] :expire expiration period or timestamp
|
64
|
-
# @yield [record] Additional block, applied as part of the save transaction
|
65
|
-
# @return [Redpear::Model] the saved record
|
66
|
-
def save(options = {}, &block)
|
67
|
-
before_save
|
68
|
-
update "id" => self.class.next_id unless persisted?
|
69
|
-
|
70
|
-
transaction do
|
71
|
-
nest.mapped_hmset __persistable_attributes__
|
72
|
-
__relevant_member_sets__.each {|s| s.add(self) }
|
73
|
-
expire options[:expire]
|
74
|
-
yield(self) if block
|
75
|
-
end
|
76
|
-
ensure
|
77
|
-
after_save
|
78
|
-
end
|
79
|
-
alias_method :save!, :save
|
80
|
-
|
81
|
-
# Destroy the record.
|
82
|
-
# @return [Boolean] true or false
|
83
|
-
def destroy
|
84
|
-
return false unless persisted?
|
85
|
-
before_destroy
|
86
|
-
|
87
|
-
transaction do
|
88
|
-
nest.del
|
89
|
-
__relevant_member_sets__.each {|s| s.remove(self) }
|
90
|
-
end
|
91
|
-
|
92
|
-
true
|
93
|
-
ensure
|
94
|
-
after_destroy
|
95
|
-
end
|
96
|
-
|
97
|
-
protected
|
98
|
-
|
99
|
-
# Run in a DB transaction, returns self
|
100
|
-
def transaction(&block)
|
101
|
-
self.class.transaction(&block)
|
102
|
-
self
|
103
|
-
end
|
104
|
-
|
105
|
-
# "Cheap" callback, override in subclasses
|
106
|
-
def before_save
|
107
|
-
end
|
108
|
-
|
109
|
-
# "Cheap" callback, override in subclasses
|
110
|
-
def after_save
|
111
|
-
end
|
112
|
-
|
113
|
-
# "Cheap" callback, override in subclasses
|
114
|
-
def before_destroy
|
115
|
-
end
|
116
|
-
|
117
|
-
# "Cheap" callback, override in subclasses
|
118
|
-
def after_destroy
|
119
|
-
end
|
120
|
-
|
121
|
-
protected
|
122
|
-
|
123
|
-
# Attributes that can be persisted
|
124
|
-
def __persistable_attributes__
|
125
|
-
result = {}
|
126
|
-
each do |key, value|
|
127
|
-
next unless self.class.columns.include?(key)
|
128
|
-
result[key] = __persistable_value__(value)
|
129
|
-
end
|
130
|
-
result
|
131
|
-
end
|
132
|
-
|
133
|
-
def __persistable_value__(value)
|
134
|
-
case value
|
135
|
-
when Time
|
136
|
-
value.to_i
|
137
|
-
else
|
138
|
-
value
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# Return relevant set nests
|
143
|
-
def __relevant_member_sets__
|
144
|
-
@__relevant_member_sets__ ||= [self.class.members] + self.class.columns.indices.map {|i| i.members(self[i]) if self[i] }.compact
|
145
|
-
end
|
146
|
-
|
147
|
-
end
|
data/lib/redpear/zindex.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
class Redpear::ZIndex < Redpear::Index
|
2
|
-
|
3
|
-
attr_reader :callback
|
4
|
-
|
5
|
-
# Creates a new ZIndex.
|
6
|
-
# @param [Redpear::Model] model
|
7
|
-
# the model the column is associated with
|
8
|
-
# @param [String] name
|
9
|
-
# the column name
|
10
|
-
# @param [Symbol] callback
|
11
|
-
# method to be call on the object, to determine the score
|
12
|
-
# @param [Symbol] type
|
13
|
-
# the column type (:string (default), :counter, :integer, :float, :timestamp)
|
14
|
-
def initialize(model, name, callback, type = nil)
|
15
|
-
super(model, name, type)
|
16
|
-
@callback = callback
|
17
|
-
end
|
18
|
-
|
19
|
-
# @param [String] value
|
20
|
-
# the index value
|
21
|
-
# @return [Redpear::SortedMembers] the IDs of all existing records for a given index value
|
22
|
-
def members(value)
|
23
|
-
Redpear::ZMembers.new nest(value), callback
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
data/lib/redpear/zmembers.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
class Redpear::ZMembers < Redpear::Members
|
2
|
-
|
3
|
-
# Constructor
|
4
|
-
# @param [Redpear::Nest] nest
|
5
|
-
# the nest object
|
6
|
-
# @param [Symbol] callback
|
7
|
-
# the method to use for scoring when members are added
|
8
|
-
def initialize(nest, callback)
|
9
|
-
super(nest)
|
10
|
-
@callback = callback.to_sym
|
11
|
-
end
|
12
|
-
|
13
|
-
# @return [Hash] the actual members
|
14
|
-
def members
|
15
|
-
@members ||= range.to_set
|
16
|
-
end
|
17
|
-
|
18
|
-
# @param [Hash] options
|
19
|
-
# @option [Integer] start, start index, defaults to 0
|
20
|
-
# @option [Integer] stop, stop index, defaults to -1
|
21
|
-
# @returns [Hash] range of members, lowest rank first
|
22
|
-
def range(options = {})
|
23
|
-
options = options.merge(:start => 0, :stop => -1)
|
24
|
-
nest.zrange options.delete(:start), options.delete(:stop), options
|
25
|
-
end
|
26
|
-
|
27
|
-
# @param [Hash] options
|
28
|
-
# @option [Integer] start, start index, defaults to 0
|
29
|
-
# @option [Integer] stop, stop index, defaults to -1
|
30
|
-
# @returns [Hash] range or members, highest rank first
|
31
|
-
def reverse_range(options = {})
|
32
|
-
options = options.merge(:start => 0, :stop => -1)
|
33
|
-
nest.zrevrange options.delete(:start), options.delete(:stop), options
|
34
|
-
end
|
35
|
-
|
36
|
-
# Is the value a member? This method is not cached, try using #include? instead.
|
37
|
-
# @param [String] value
|
38
|
-
def is_member?(value)
|
39
|
-
!!nest.zscore(value)
|
40
|
-
end
|
41
|
-
|
42
|
-
# @return [Integer] the cardinality of this set.
|
43
|
-
# This method is not cached, try using #count instead.
|
44
|
-
def cardinality
|
45
|
-
nest.zcard
|
46
|
-
end
|
47
|
-
|
48
|
-
# @return [Integer] the score for a member
|
49
|
-
# This method is not cached.
|
50
|
-
def score(value)
|
51
|
-
nest.zscore(value)
|
52
|
-
end
|
53
|
-
|
54
|
-
# Add a member to this set
|
55
|
-
# @param [Model] record
|
56
|
-
def add(record)
|
57
|
-
@members << record.id if loaded?
|
58
|
-
nest.zadd(record.send(@callback), record.id)
|
59
|
-
end
|
60
|
-
|
61
|
-
# Remove a member from this set
|
62
|
-
# @param [Model] record
|
63
|
-
def remove(record, score = 0)
|
64
|
-
@members.delete(record.id) if loaded?
|
65
|
-
nest.zrem(record.id)
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|