class RedisOrm::Associations::HasManyProxy

Public Class Methods

new(receiver_model_name, reciever_id, foreign_models, options) click to toggle source
   # File lib/redis_orm/associations/has_many_proxy.rb
 6 def initialize(receiver_model_name, reciever_id, foreign_models, options)
 7   @records = [] #records.to_a
 8   @reciever_model_name = receiver_model_name
 9   @reciever_id = reciever_id
10   @foreign_models = foreign_models
11   @options = options
12   @fetched = false
13 end

Public Instance Methods

<<(new_records) click to toggle source

user = User.find(1) user.avatars << Avatar.find(23) => user:1:avatars => [23]

   # File lib/redis_orm/associations/has_many_proxy.rb
36 def <<(new_records)
37   new_records.to_a.each do |record|
38     $redis.zadd(__key__, Time.now.to_f, record.id)
39     
40     receiver_instance.set_expire_on_reference_key(__key__)
41     
42     record.get_indices.each do |index|
43       save_index_for_associated_record(index, record, [@reciever_model_name, @reciever_id, record.model_name.pluralize]) # record.model_name.pluralize => @foreign_models
44     end
45 
46     if !@options[:as]
47       record_associations = record.get_associations
48 
49       # article.comments << [comment1, comment2]
50       # iterate through the array of comments and create backlink
51       # check whether *record* object has *has_many* declaration and TODO it states *self.model_name* in plural and there is no record yet from the *record*'s side (in order not to provoke recursion)
52       if has_many_assoc = record_associations.detect{|h| h[:type] == :has_many && h[:foreign_models] == @reciever_model_name.pluralize.to_sym}
53         pluralized_reciever_model_name = if has_many_assoc[:options][:as]
54           has_many_assoc[:options][:as].pluralize
55         else
56           @reciever_model_name.pluralize
57         end
58 
59         reference_key = "#{record.model_name}:#{record.id}:#{pluralized_reciever_model_name}"
60         
61         if !$redis.zrank(reference_key, @reciever_id)
62           $redis.zadd(reference_key, Time.now.to_f, @reciever_id)
63           receiver_instance.set_expire_on_reference_key(reference_key)
64         end
65       # check whether *record* object has *has_one* declaration and TODO it states *self.model_name* and there is no record yet from the *record*'s side (in order not to provoke recursion)
66       elsif has_one_assoc = record_associations.detect{|h| [:has_one, :belongs_to].include?(h[:type]) && h[:foreign_model] == @reciever_model_name.to_sym}
67         reciever_model_name = if has_one_assoc[:options][:as]
68           has_one_assoc[:options][:as].to_sym
69         else
70           @reciever_model_name
71         end
72         if record.send(reciever_model_name).nil?
73           key = "#{record.model_name}:#{record.id}:#{reciever_model_name}"
74           $redis.set(key, @reciever_id)
75           receiver_instance.set_expire_on_reference_key(key)
76         end
77       end
78     end
79   end
80   
81   # return *self* here so calls could be chained
82   self
83 end
[](index) click to toggle source
   # File lib/redis_orm/associations/has_many_proxy.rb
24 def [](index)
25   fetch if !@fetched
26   @records[index]
27 end
all(options = {}) click to toggle source
    # File lib/redis_orm/associations/has_many_proxy.rb
 85 def all(options = {})
 86   if options.is_a?(Hash) && (options[:limit] || options[:offset] || options[:order] || options[:conditions])
 87     limit = if options[:limit] && options[:offset]
 88       [options[:offset].to_i, options[:limit].to_i]            
 89     elsif options[:limit]
 90       [0, options[:limit].to_i]
 91     end
 92 
 93     prepared_index = if options[:conditions] && options[:conditions].is_a?(Hash)
 94       properties = options[:conditions].collect{|key, value| key}
 95 
 96       index = @foreign_models.to_s.singularize.camelize.constantize.find_indices(properties, :first => true)
 97 
 98       raise NotIndexFound if !index
 99 
100       construct_prepared_index(index, options[:conditions])
101     else
102       __key__
103     end
104 
105     @records = []
106 
107     # to DRY things up I use here check for index but *else* branch also imply that the index might have be used
108     # since *prepared_index* vary whether options[:conditions] are present or not
109     if index && index[:options][:unique]
110       id = $redis.get prepared_index
111       @records << @foreign_models.to_s.singularize.camelize.constantize.find(id)
112     else
113       ids = if options[:order].to_s == 'desc'
114         $redis.zrevrangebyscore(prepared_index, Time.now.to_f, 0, :limit => limit)
115       else
116         $redis.zrangebyscore(prepared_index, 0, Time.now.to_f, :limit => limit)
117       end
118       @records += @foreign_models.to_s.singularize.camelize.constantize.find(ids)
119     end
120     @fetched = true
121     @records
122   else
123     fetch if !@fetched
124     @records
125   end
126 end
count() click to toggle source
    # File lib/redis_orm/associations/has_many_proxy.rb
151 def count
152   $redis.zcard __key__
153 end
delete(id) click to toggle source
    # File lib/redis_orm/associations/has_many_proxy.rb
147 def delete(id)
148   $redis.zrem(__key__, id.to_i)
149 end
fetch() click to toggle source
   # File lib/redis_orm/associations/has_many_proxy.rb
19 def fetch
20   @records = @foreign_models.to_s.singularize.camelize.constantize.find($redis.zrevrangebyscore __key__, Time.now.to_f, 0)
21   @fetched = true
22 end
find(token = nil, options = {}) click to toggle source
    # File lib/redis_orm/associations/has_many_proxy.rb
128 def find(token = nil, options = {})
129   if token.is_a?(String) || token.is_a?(Integer)
130     record_id = $redis.zrank(__key__, token.to_i)
131     if record_id
132       @fetched = true
133       @records = @foreign_models.to_s.singularize.camelize.constantize.find(token)
134     else
135       nil
136     end
137   elsif token == :all
138     all(options)
139   elsif token == :first
140     all(options.merge({:limit => 1}))[0]
141   elsif token == :last
142     reversed = options[:order] == 'desc' ? 'asc' : 'desc'
143     all(options.merge({:limit => 1, :order => reversed}))[0]
144   end
145 end
method_missing(method_name, *args, &block) click to toggle source
    # File lib/redis_orm/associations/has_many_proxy.rb
155 def method_missing(method_name, *args, &block)
156   fetch if !@fetched
157   @records.send(method_name, *args, &block)        
158 end
receiver_instance() click to toggle source
   # File lib/redis_orm/associations/has_many_proxy.rb
15 def receiver_instance
16   @receiver_instance ||= @reciever_model_name.camelize.constantize.find(@reciever_id)
17 end
to_a() click to toggle source
   # File lib/redis_orm/associations/has_many_proxy.rb
29 def to_a
30   fetch if !@fetched
31   @records        
32 end

Protected Instance Methods

__key__() click to toggle source

helper method

    # File lib/redis_orm/associations/has_many_proxy.rb
163 def __key__
164   @options[:as] ? "#{@reciever_model_name}:#{@reciever_id}:#{@options[:as]}" : "#{@reciever_model_name}:#{@reciever_id}:#{@foreign_models}"
165 end
construct_prepared_index(index, conditions_hash) click to toggle source

“article:1:comments:moderated:true”

    # File lib/redis_orm/associations/has_many_proxy.rb
168 def construct_prepared_index(index, conditions_hash)
169   prepared_index = [@reciever_model_name, @reciever_id, @foreign_models].join(':')
170   
171   # in order not to depend on order of keys in *:conditions* hash we rather interate over the index itself and find corresponding values in *:conditions* hash
172   if index[:name].is_a?(Array)
173     index[:name].each do |key|
174       # raise if User.find_by_firstname_and_castname => there's no *castname* in User's properties
175       #raise ArgumentsMismatch if !@@properties[model_name].detect{|p| p[:name] == key.to_sym} # TODO
176       prepared_index += ":#{key}:#{conditions_hash[key]}"
177     end
178   else
179     prepared_index += ":#{index[:name]}:#{conditions_hash[index[:name]]}"
180   end
181 
182   prepared_index.downcase! if index[:options][:case_insensitive]
183 
184   prepared_index
185 end