module Mongoid::Denormalization::ClassMethods
Public Instance Methods
denormalize_from(relation, field_name, denormalized_field_name: nil, to_klass_infos: [])
click to toggle source
Calls superclass method
# File lib/mongoid/denormalization.rb, line 42 def denormalize_from(relation, field_name, denormalized_field_name: nil, to_klass_infos: []) to_klass = self field_terms = field_name.to_s.split(".") denormalized_field_name ||= [relation, field_terms.last].flatten.join("_") if to_klass_infos.blank? && !(to_klass.embedded?) to_klass_infos = [{ klasses: [to_klass], selector_proc: Proc.new do |id, value| {"#{relation}_id".to_sym => id, denormalized_field_name.to_sym => {"$ne" => value}} end, updator: denormalized_field_name, index_key: "#{relation}_id" }] end # to_klass_infos.each do |to_klass_info| # index_key = to_klass_info[:index_key] # raise "Index key is blank" if index_key.blank? # to_klass_info[:klasses].each do |klass| # if klass.collection.indexes.to_a.select{|index_info| index_info["key"].keys.index(index_key) == 0}.blank? # raise "Index missing exception for #{index_key} on #{klass.to_s} class" # end # end # end to_klass_roots = to_klass_infos.map{|to_klass_info| to_klass_info[:klasses].map(&:to_s)}.flatten.uniq from_klass = self.relations[relation.to_s].class_name.constantize field_type = from_klass.fields[field_name.to_s].options[:type] if field_terms.size == 1 && field_name.to_s != "_type" field_type ||= String to_klass_infos.each do |to_klass_info| next unless to_klass_info[:index_key].include?(".") field_path = to_klass_info[:index_key].split(".").first to_klass_info[:klasses].each do |klass| unless klass.method_defined?(:force_denormalize) klass.send(:define_method, :force_denormalize) do end end unless klass.method_defined?(:force_denormalize!) klass.send(:define_method, :force_denormalize!) do force_denormalize self.save end end unless klass.method_defined?("force_denormalize_#{field_path}".to_sym) klass.send(:define_method, "force_denormalize_#{field_path}".to_sym) do docs = self.send(field_path.to_sym) if docs.respond_to?(:each) docs.each{|doc| doc.force_denormalize} else docs.force_denormalize end end force_denormalize_module = Module.new do define_method "force_denormalize" do |*args| super(*args) self.send("force_denormalize_#{field_path}") end end klass.prepend(force_denormalize_module) end end end from_klass.instance_eval do after_save do |from_doc| changed_fn = "#{field_terms[0]}_changed?" changed_fn = "asset_filename_changed?" if field_terms[0].to_s == "asset" if from_doc.send(changed_fn) field_value = ::Mongoid::Denormalization::Helpers.field_value(from_doc, field_terms) ::Mongoid::Denormalization::Helpers.update_from_klass_changes(to_klass_infos, from_doc.id, field_value) end end after_destroy do |from_doc| field_value = nil ::Mongoid::Denormalization::Helpers.update_from_klass_changes(to_klass_infos, from_doc.id, field_value) end end to_klass.class_eval do get_func_module = Module.new do define_method denormalized_field_name.to_s do |*args| use_denormalized = to_klass_roots.find{|to_klass_root| self._root.is_a?(to_klass_root.constantize)}.present? field_value = super(*args) if use_denormalized return field_value if field_value.present? from_doc = self.send(relation) return nil if from_doc.blank? field_value = ::Mongoid::Denormalization::Helpers.field_value(from_doc, field_terms) if use_denormalized self.send("#{denormalized_field_name}=", field_value) self.set("#{denormalized_field_name}" => field_value) if self.persisted? end return field_value end end self.prepend(get_func_module) define_method "denormalize_#{denormalized_field_name}" do use_denormalized = to_klass_roots.find{|to_klass_root| self._root.is_a?(to_klass_root.constantize)}.present? return unless use_denormalized from_doc = self.send(relation) return nil if from_doc.blank? field_value = ::Mongoid::Denormalization::Helpers.field_value(from_doc, field_terms) self.send("#{denormalized_field_name}=", field_value) return true end define_method "denormalize_#{denormalized_field_name}!" do use_denormalized = to_klass_roots.find{|to_klass_root| self._root.is_a?(to_klass_root.constantize)}.present? return unless use_denormalized from_doc = self.send(relation) return nil if from_doc.blank? field_value = ::Mongoid::Denormalization::Helpers.field_value(from_doc, field_terms) self.set(denormalized_field_name.to_sym => field_value) end force_denormalize_module = Module.new do define_method "force_denormalize" do |*args| super(*args) self.send("denormalize_#{denormalized_field_name}") end end self.prepend(force_denormalize_module) end to_klass.instance_eval do self.field(denormalized_field_name, type: field_type) before_save do |doc| if doc.send("#{relation}_id_changed?") doc.send("denormalize_#{denormalized_field_name}") end end end end