Class: RedisOrm::Associations::HasManyProxy

Inherits:
Object
  • Object
show all
Includes:
HasManyHelper
Defined in:
lib/redis_orm/associations/has_many_proxy.rb

Instance Method Summary collapse

Constructor Details

#initialize(receiver_model_name, reciever_id, foreign_models, options) ⇒ HasManyProxy

Returns a new instance of HasManyProxy.



6
7
8
9
10
11
12
13
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 6

def initialize(receiver_model_name, reciever_id, foreign_models, options)
  @records = [] #records.to_a
  @reciever_model_name = receiver_model_name
  @reciever_id = reciever_id
  @foreign_models = foreign_models
  @options = options
  @fetched = false
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object



155
156
157
158
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 155

def method_missing(method_name, *args, &block)
  fetch if !@fetched
  @records.send(method_name, *args, &block)        
end

Instance Method Details

#<<(new_records) ⇒ Object

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



36
37
38
39
40
41
42
43
44
45
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
78
79
80
81
82
83
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 36

def <<(new_records)
  new_records.to_a.each do |record|
    $redis.zadd(__key__, Time.now.to_f, record.id)
    
    receiver_instance.set_expire_on_reference_key(__key__)
    
    record.get_indices.each do |index|
      save_index_for_associated_record(index, record, [@reciever_model_name, @reciever_id, record.model_name.pluralize]) # record.model_name.pluralize => @foreign_models
    end

    if !@options[:as]
      record_associations = record.get_associations

      # article.comments << [comment1, comment2] 
      # iterate through the array of comments and create backlink
      # 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)                    
      if has_many_assoc = record_associations.detect{|h| h[:type] == :has_many && h[:foreign_models] == @reciever_model_name.pluralize.to_sym}
        pluralized_reciever_model_name = if has_many_assoc[:options][:as]
          has_many_assoc[:options][:as].pluralize
        else
          @reciever_model_name.pluralize
        end

        reference_key = "#{record.model_name}:#{record.id}:#{pluralized_reciever_model_name}"
        
        if !$redis.zrank(reference_key, @reciever_id)
          $redis.zadd(reference_key, Time.now.to_f, @reciever_id)
          receiver_instance.set_expire_on_reference_key(reference_key)
        end
      # 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)
      elsif has_one_assoc = record_associations.detect{|h| [:has_one, :belongs_to].include?(h[:type]) && h[:foreign_model] == @reciever_model_name.to_sym}
        reciever_model_name = if has_one_assoc[:options][:as]
          has_one_assoc[:options][:as].to_sym
        else
          @reciever_model_name
        end
        if record.send(reciever_model_name).nil?
          key = "#{record.model_name}:#{record.id}:#{reciever_model_name}"
          $redis.set(key, @reciever_id)
          receiver_instance.set_expire_on_reference_key(key)
        end
      end
    end
  end
  
  # return *self* here so calls could be chained
  self
end

#[](index) ⇒ Object



24
25
26
27
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 24

def [](index)
  fetch if !@fetched
  @records[index]
end

#all(options = {}) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 85

def all(options = {})
  if options.is_a?(Hash) && (options[:limit] || options[:offset] || options[:order] || options[:conditions])
    limit = if options[:limit] && options[:offset]
      [options[:offset].to_i, options[:limit].to_i]            
    elsif options[:limit]
      [0, options[:limit].to_i]
    end

    prepared_index = if options[:conditions] && options[:conditions].is_a?(Hash)
      properties = options[:conditions].collect{|key, value| key}

      index = @foreign_models.to_s.singularize.camelize.constantize.find_indices(properties, :first => true)

      raise NotIndexFound if !index

      construct_prepared_index(index, options[:conditions])
    else
      __key__
    end

    @records = []

    # to DRY things up I use here check for index but *else* branch also imply that the index might have be used
    # since *prepared_index* vary whether options[:conditions] are present or not
    if index && index[:options][:unique]
      id = $redis.get prepared_index
      @records << @foreign_models.to_s.singularize.camelize.constantize.find(id)
    else
      ids = if options[:order].to_s == 'desc'
        $redis.zrevrangebyscore(prepared_index, Time.now.to_f, 0, :limit => limit)
      else
        $redis.zrangebyscore(prepared_index, 0, Time.now.to_f, :limit => limit)
      end
      @records += @foreign_models.to_s.singularize.camelize.constantize.find(ids)
    end
    @fetched = true
    @records
  else
    fetch if !@fetched
    @records
  end
end

#countObject



151
152
153
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 151

def count
  $redis.zcard __key__
end

#delete(id) ⇒ Object



147
148
149
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 147

def delete(id)
  $redis.zrem(__key__, id.to_i)
end

#fetchObject



19
20
21
22
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 19

def fetch
  @records = @foreign_models.to_s.singularize.camelize.constantize.find($redis.zrevrangebyscore __key__, Time.now.to_f, 0)
  @fetched = true
end

#find(token = nil, options = {}) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 128

def find(token = nil, options = {})
  if token.is_a?(String) || token.is_a?(Integer)
    record_id = $redis.zrank(__key__, token.to_i)
    if record_id
      @fetched = true
      @records = @foreign_models.to_s.singularize.camelize.constantize.find(token)
    else
      nil
    end
  elsif token == :all
    all(options)
  elsif token == :first
    all(options.merge({:limit => 1}))[0]
  elsif token == :last
    reversed = options[:order] == 'desc' ? 'asc' : 'desc'
    all(options.merge({:limit => 1, :order => reversed}))[0]
  end
end

#receiver_instanceObject



15
16
17
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 15

def receiver_instance
  @receiver_instance ||= @reciever_model_name.camelize.constantize.find(@reciever_id)
end

#to_aObject



29
30
31
32
# File 'lib/redis_orm/associations/has_many_proxy.rb', line 29

def to_a
  fetch if !@fetched
  @records        
end