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