Class: Redisted::Base

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Callbacks, ActiveModel::Naming, ActiveModel::Translation
Includes:
ActiveModel::MassAssignmentSecurity, ActiveModel::Serialization, ActiveModel::Validations
Defined in:
lib/redisted/base.rb,
lib/redisted/index.rb,
lib/redisted/delete.rb,
lib/redisted/fields.rb,
lib/redisted/relation.rb,
lib/redisted/getsetattr.rb,
lib/redisted/references.rb,
lib/redisted/instantiate.rb

Defined Under Namespace

Classes: Relation

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attrs = nil, redis = nil) ⇒ Base

Returns a new instance of Base.



21
22
23
24
25
26
27
28
29
30
# File 'lib/redisted/base.rb', line 21

def initialize(attrs = nil,redis=nil)
  @redis=redis||Base.redis
  validate_redis
  init_fields
  init_attributes
  init_indexes
  init_references
  self.attributes=attrs if attrs
  self
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(id, *args) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/redisted/base.rb', line 69

def method_missing(id, *args)
  fields.each do |field,options|
    return get_attr(field) if id==field
    return set_attr(field,args[0]) if id.to_s==field.to_s+"="
  end
  references.each do |ref,options|
    return get_reference(ref,options) if id==ref
    return set_reference(ref,options,args[0]) if id.to_s==ref.to_s+"="
  end
  super
end

Class Method Details

.always_cache_until_save(val = true) ⇒ Object



4
5
6
# File 'lib/redisted/getsetattr.rb', line 4

def always_cache_until_save val=true
  set_obj_option :cache_until_save,val
end

.create(attrs = nil, redis = nil) ⇒ Object

Use



7
8
9
10
11
# File 'lib/redisted/instantiate.rb', line 7

def create attrs=nil,redis=nil
  ret=new attrs,redis
  ret.save
  ret
end

.field(value, options = {}) ⇒ Object

Setup



17
18
19
20
# File 'lib/redisted/fields.rb', line 17

def field value,options={}
  options[:type]||=:string
  fields[value]=options
end

.fieldsObject



21
22
23
24
# File 'lib/redisted/fields.rb', line 21

def fields
  @fields||={}
  @fields
end

.fields=(val) ⇒ Object



25
26
27
# File 'lib/redisted/fields.rb', line 25

def fields= val
  @fields=val
end

.find(ids) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/redisted/instantiate.rb', line 12

def find ids
  if ids.is_a? Array
    ret=[]
    ids.each do |id|
      m=new
      m.load id
      ret << m
    end
    ret
  else
    m=new
    m.load ids
    m
  end
end

.get_obj_option(key) ⇒ Object



99
100
101
102
# File 'lib/redisted/base.rb', line 99

def get_obj_option key
  @obj_options||={}
  @obj_options[key]
end

.index(name, params) ⇒ Object

Raises:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/redisted/index.rb', line 46

def index name,params
  raise InvalidIndex,"Index redefined: #{name}" if indices[name]
  entry={
      redis_key: "#{prefix}[#{name}]",
      optimistic_retry: params[:optimistic_retry],
  }
  if params[:unique]
    entry[:unique_index]=true
    entry[:fields]= if params[:unique].is_a? Array
                      params[:unique]
                    elsif params[:unique].is_a? Symbol
                      [params[:unique]]
                    else
                      [name]
                    end
  else
    entry[:unique_index]=false
    entry[:includes]=lambdafi_index(params[:includes],true)
    entry[:order]=lambdafi_index(params[:order],1)
    entry[:match]=lambdafi_index(params[:match],"") if params[:match]
    entry[:fields]= if params[:fields].nil?
                      nil
                    elsif params[:fields].is_a? Array
                      params[:fields]
                    elsif params[:fields].is_a? Symbol
                      [params[:fields]]
                    else
                      nil
                    end
  end
  indices[name]=entry
end

.indicesObject



42
43
44
45
# File 'lib/redisted/index.rb', line 42

def indices
  @indices||={}
  @indices
end

.indices=(val) ⇒ Object



39
40
41
# File 'lib/redisted/index.rb', line 39

def indices= val
  @indices=val
end

.is_redisted_model?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/redisted/base.rb', line 107

def is_redisted_model?
  true
end

.lambdafi_index(options, default_value) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/redisted/index.rb', line 78

def lambdafi_index options,default_value
  lambda do |*args|
    ret=nil
    if options.nil?
      ret=default_value
    elsif options.respond_to? :call
      ret=options.call(*args)
    elsif options.is_a? Symbol
      ret=args[0].send(options,*args)
    else
      ret=options # An integer or other constant value...
    end
    ret
  end
end

.method_missing(id, *args, &proc) ⇒ Object



180
181
182
183
184
185
186
187
# File 'lib/redisted/relation.rb', line 180

def method_missing(id,*args,&proc)
  is_scoped=(id[0]=='_')
  is_scoped||=[:first,:last,:all,:each,:delete_all,:destroy_all,:where,:limit,:offset,:order,:reverse_order].include? id.to_sym
  is_scoped||= !scopes[id.to_sym].nil?
  is_scoped||= (id[0,3]=="by_")
  return scoped.send(id,*args,&proc) if is_scoped
  super
end

.pre_cache_all(opts = {}) ⇒ Object



7
8
9
10
11
# File 'lib/redisted/getsetattr.rb', line 7

def pre_cache_all opts={}
  opts[:keys]=:all if opts[:keys].nil?
  opts[:when]=:create if opts[:when].nil?
  set_obj_option :pre_cache_all,opts
end

.prefixObject



116
117
118
119
# File 'lib/redisted/base.rb', line 116

def prefix
  ret=self.model_name.i18n_key
  ret
end

.redisObject



113
114
115
# File 'lib/redisted/base.rb', line 113

def redis
  @@redis
end

.redis=(conn) ⇒ Object



110
111
112
# File 'lib/redisted/base.rb', line 110

def redis= conn
  @@redis=conn
end

.referencesObject



10
11
12
13
# File 'lib/redisted/references.rb', line 10

def references
  @references||={}
  @references
end

.references=(val) ⇒ Object



7
8
9
# File 'lib/redisted/references.rb', line 7

def references= val
  @references=val
end

.references_many(sym, opt = {}) ⇒ Object

Raises:



60
61
62
63
64
65
66
# File 'lib/redisted/references.rb', line 60

def references_many sym,opt={}
  details=name_to_class_details sym,opt[:as]
  raise InvalidReference,"Reference already defined" if !references[details[:plural][:symbol]].nil?
  field "#{details[:plural][:string]}_list".to_sym
  details[:ref_type]=:many
  references[details[:plural][:symbol]]=details
end

.references_one(sym, opt = {}) ⇒ Object

Setup

Raises:



53
54
55
56
57
58
59
# File 'lib/redisted/references.rb', line 53

def references_one sym,opt={}
  details=name_to_class_details sym,opt[:as]
  raise InvalidReference,"Reference already defined" if !references[details[:symbol]].nil?
  field "#{details[:string]}_id".to_sym
  details[:ref_type]=:one
  references[details[:symbol]]=details
end

.scope(name, options) ⇒ Object



35
36
37
# File 'lib/redisted/fields.rb', line 35

def scope name,options
  scopes[name]=lambdafi_field(options)
end

.scopedObject



177
178
179
# File 'lib/redisted/relation.rb', line 177

def scoped
  Relation.new self,@@redis,scopes,indices
end

.scopesObject



28
29
30
31
# File 'lib/redisted/fields.rb', line 28

def scopes
  @scopes||={}
  @scopes
end

.scopes=(val) ⇒ Object



32
33
34
# File 'lib/redisted/fields.rb', line 32

def scopes= val
  @scopes=val
end

.set_obj_option(key, val) ⇒ Object



103
104
105
106
# File 'lib/redisted/base.rb', line 103

def set_obj_option key,val
  @obj_options||={}
  @obj_options[key]=val
end

Instance Method Details

#attributes(load_all = true) ⇒ Object



159
160
161
162
# File 'lib/redisted/getsetattr.rb', line 159

def attributes load_all=true
  fill_cache if load_all
  @attributes_value.merge id: @id
end

#attributes=(attrs) ⇒ Object



152
153
154
155
156
157
158
# File 'lib/redisted/getsetattr.rb', line 152

def attributes= attrs
  cache do
    attrs.each do |key,value|
      set_attr key,value
    end
  end
end

#cacheObject



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/redisted/getsetattr.rb', line 125

def cache
  if block_given?
    previous_cached_sets=nil
    begin
      previous_cached_sets=@cached_sets
      @cached_sets=true
      yield
      save if !previous_cached_sets
      @cached_sets=previous_cached_sets
    rescue Exception
      @cached_sets=previous_cached_sets
      raise
    end
  else
    @cached_sets=true
  end
end

#cache!(&proc) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/redisted/getsetattr.rb', line 142

def cache! &proc
  begin
    @cached_sets=true
    proc.call *attrs
    save!
  rescue Exception
    @cached_sets=false
    raise
  end
end

#cached?(key) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
113
# File 'lib/redisted/getsetattr.rb', line 110

def cached? key
  return true if !persisted?
  return [:cached,:dirty].include?(@attributes_status[key])
end

#clear(key = nil) ⇒ Object



73
74
75
76
77
78
79
80
81
# File 'lib/redisted/getsetattr.rb', line 73

def clear key=nil
  if key.nil?
    self.class.fields.each do |key,val|
      raise IsDirty,"#{key} is dirty" if (!key.nil?) and @attributes_status[key]==:dirty
    end
  end
  setup_attributes
  nil
end

#deleteObject



4
5
6
7
8
9
10
11
12
# File 'lib/redisted/delete.rb', line 4

def delete
  raise Redisted::RecordInvalid,"Object is not persisted" if self.id.nil?
  @redis.del "#{prefix}:#{self.id}"
  id=nil
  attributes={}
  @attributes_status.clear
  # LEELEE: Also handle indices
  true
end

#destroyObject



13
14
15
16
17
18
# File 'lib/redisted/delete.rb', line 13

def destroy
  # TODO: Run all the callbacks...
  delete
  # LEELEE: Follow destroy path...
  true
end

#dirty?(key) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
117
# File 'lib/redisted/getsetattr.rb', line 114

def dirty? key
  return true if !persisted?
  return @attributes_status[key]==:dirty
end

#fieldsObject



3
4
5
# File 'lib/redisted/fields.rb', line 3

def fields
  self.class.fields
end

#fill_cache(keys = nil) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/redisted/getsetattr.rb', line 87

def fill_cache keys=nil
  if keys.nil?
    keys=[]
    fields.each do |key,val|
      next if !@attributes_status[key].nil?
      keys << key
    end
  end
  if keys.size>0
    ret=@redis.hmget  "#{prefix}:#{@id}",*keys
    idx=0
    keys.each do |key|
      key=key.to_sym
      @attributes_value[key]=ret[idx]
      @attributes_status[key]=:cached
      idx+=1
    end
  end
  self
end

#flushObject



82
83
84
85
86
# File 'lib/redisted/getsetattr.rb', line 82

def flush
  fields.each do |key,val|
    @attributes_status[key]=nil
  end
end

#get_attr(key) ⇒ Object



62
63
64
65
66
67
68
69
70
71
# File 'lib/redisted/getsetattr.rb', line 62

def get_attr key
  key=key.to_sym
  return to_attr_type(key,@attributes_value[key]) if [:cached,:dirty].include?(@attributes_status[key])
  return nil if !persisted?
  ret=to_attr_type key,@redis.hget("#{prefix}:#{@id}",key)
  pre_cache_values if get_obj_option(:pre_cache_all) and get_obj_option(:pre_cache_all)[:when]==:first_read and !@cache_preload
  @attributes_value[key]=ret
  @attributes_status[key]=:cached
  ret
end

#idObject

NOTE: ID is read/only - it can only be set via the load method



43
44
45
# File 'lib/redisted/base.rb', line 43

def id # NOTE: ID is read/only - it can only be set via the load method
  @id
end

#indicesObject

Setup



35
36
37
# File 'lib/redisted/index.rb', line 35

def indices
  self.class.indices
end

#internal_only_force_update_attributes(attr, status) ⇒ Object



324
325
326
327
# File 'lib/redisted/index.rb', line 324

def internal_only_force_update_attributes attr,status
  @attributes_value=attr
  @attributes_status=status
end

#load(id) ⇒ Object



28
29
30
31
32
# File 'lib/redisted/instantiate.rb', line 28

def load id
  @id=id
  pre_cache_values if get_obj_option(:pre_cache_all) and get_obj_option(:pre_cache_all)[:when]==:create
  self
end

#persisted?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/redisted/getsetattr.rb', line 107

def persisted?
  !@id.nil?
end

#prefixObject



40
41
42
# File 'lib/redisted/base.rb', line 40

def prefix
  self.class.prefix
end

#redisObject



36
37
38
39
# File 'lib/redisted/base.rb', line 36

def redis
  validate_redis
  @redis
end

#redis=(conn = nil) ⇒ Object



31
32
33
34
35
# File 'lib/redisted/base.rb', line 31

def redis= conn=nil
  @redis=conn||@@redis
  validate_redis
  @redis
end

#referencesObject



3
4
5
# File 'lib/redisted/references.rb', line 3

def references
  self.class.references
end

#save(options = {}) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/redisted/getsetattr.rb', line 169

def save options={}
  begin
    if (options[:validate].nil? or options[:validate])
      raise Redisted::RecordInvalid if !valid?
    end
    internal_save_with_callbacks
  rescue Exception=>err
    self.errors[:base] = err.to_s
    return false
  end
  true
end

#save!Object



164
165
166
167
# File 'lib/redisted/getsetattr.rb', line 164

def save!
  raise Redisted::RecordInvalid if !valid?
  internal_save_with_callbacks
end

#saved?Boolean

Returns:

  • (Boolean)


118
119
120
121
122
123
124
# File 'lib/redisted/getsetattr.rb', line 118

def saved?
  return false if !persisted?
  fields.each do |key,val|
    return false if @attributes_status[key]==:dirty
  end
  return true
end

#scopesObject



6
7
8
# File 'lib/redisted/fields.rb', line 6

def scopes
  self.class.scopes
end

#set_attr(key, val) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/redisted/getsetattr.rb', line 41

def set_attr key,val
  key=key.to_sym
  val=to_redis_type key,val
  if @cached_sets or !persisted?
    if (@attributes_status[key]==:cached)
      # If we have it, we save the old value when first marked dirty...
      @attributes_old[key]=@attributes_value[key]
      @attributes_old_status[key]=:cached
    end
    @attributes_value[key]=val
    @attributes_status[key]=:dirty
  else
    index_process({key=>val}) do
      @attributes_value[key]=val
      @attributes_status[key]=:cached
      @redis.hset "#{prefix}:#{@id}",key,val
      @attributes_old[key]=nil
      @attributes_old_status[key]=nil
    end
  end
end

#to_attr_type(key, value) ⇒ Object

Raises:



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/redisted/base.rb', line 46

def to_attr_type key,value
  raise InvalidField,"Unknown field: #{key}" if fields[key].nil?
  return nil if value.nil?
  case fields[key][:type]
    when :string then value
    when :symbol then value.to_sym
    when :integer then value.to_i
    when :datetime then value.to_datetime
    else
      value
    end
end

#to_redis_type(key, value) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/redisted/base.rb', line 58

def to_redis_type key,value
  return nil if value.nil?
  case fields[key][:type]
    when :string then value
    when :symbol then value.to_s
    when :integer then value.to_i.to_s
    when :datetime then value.utc.to_s
    else
      value
  end
end