module RedisOrm::Associations::HasOne

Public Instance Methods

has_one(foreign_model, options = {}) click to toggle source

user.avatars => user:1:avatars => [1, 22, 234] => Avatar.find([1, 22, 234]) options is a hash and can hold:

*:as* key
*:dependant* key: either *destroy* or *nullify* (default)
   # File lib/redis_orm/associations/has_one.rb
 8 def has_one(foreign_model, options = {})
 9   class_associations = class_variable_get(:"@@associations")
10   class_associations[model_name] << {:type => :has_one, :foreign_model => foreign_model, :options => options}
11 
12   foreign_model_name = if options[:as]
13     options[:as].to_sym
14   else
15     foreign_model.to_sym
16   end
17 
18   if options[:index]
19     class_variable_get(:"@@indices")[model_name] << {:name => foreign_model_name, :options => {:reference => true}}
20   end
21   
22   define_method foreign_model_name do
23     foreign_model.to_s.camelize.constantize.find($redis.get "#{model_name}:#{@id}:#{foreign_model_name}")
24   end     
25 
26   # profile = Profile.create :title => 'test'
27   # user.profile = profile => user:23:profile => 1
28   define_method "#{foreign_model_name}=" do |assoc_with_record|
29     # we need to store this to clear old associations later
30     old_assoc = self.send(foreign_model_name)
31 
32     reference_key = "#{model_name}:#{id}:#{foreign_model_name}"
33     if assoc_with_record.nil?
34       $redis.del(reference_key)
35     elsif assoc_with_record.model_name == foreign_model.to_s
36       $redis.set(reference_key, assoc_with_record.id)
37       set_expire_on_reference_key(reference_key)
38     else
39       raise TypeMismatchError
40     end
41     
42     # handle indices for references
43     self.get_indices.select{|index| index[:options][:reference]}.each do |index|
44       # delete old reference that points to the old associated record
45       if !old_assoc.nil?
46         prepared_index = [self.model_name, index[:name], old_assoc.id].join(':')
47         prepared_index.downcase! if index[:options][:case_insensitive]
48 
49         if index[:options][:unique]
50           $redis.del(prepared_index, id)
51         else
52           $redis.zrem(prepared_index, id)
53         end
54       end
55       
56       # if new associated record is nil then skip to next index (since old associated record was already unreferenced)
57       next if assoc_with_record.nil?
58       
59       prepared_index = [self.model_name, index[:name], assoc_with_record.id].join(':')
60 
61       prepared_index.downcase! if index[:options][:case_insensitive]
62 
63       if index[:options][:unique]
64         $redis.set(prepared_index, id)
65       else
66         $redis.zadd(prepared_index, Time.now.to_f, id)
67       end
68     end
69 
70     if !options[:as]
71       if assoc_with_record.nil?
72         # remove old assoc
73         $redis.zrem("#{old_assoc.model_name}:#{old_assoc.id}:#{model_name.to_s.pluralize}", id) if old_assoc
74       else
75         # check whether *assoc_with_record* object has *belongs_to* declaration and TODO it states *self.model_name* and there is no record yet from the *assoc_with_record*'s side (in order not to provoke recursion)
76         if class_associations[assoc_with_record.model_name].detect{|h| [:belongs_to, :has_one].include?(h[:type]) && h[:foreign_model] == model_name.to_sym} && assoc_with_record.send(model_name.to_sym).nil?
77           # old association is being rewritten here automatically so we don't have to worry about it
78           assoc_with_record.send("#{model_name}=", self)
79         elsif class_associations[assoc_with_record.model_name].detect{|h| :has_many == h[:type] && h[:foreign_models] == model_name.to_s.pluralize.to_sym} && !$redis.zrank("#{assoc_with_record.model_name}:#{assoc_with_record.id}:#{model_name.pluralize}", self.id)
80           # remove old assoc
81           $redis.zrem("#{old_assoc.model_name}:#{old_assoc.id}:#{model_name.to_s.pluralize}", id) if old_assoc
82           # create/add new ones
83           assoc_with_record.send(model_name.pluralize.to_sym).send(:"<<", self)
84         end
85       end
86     end
87   end
88 end