Module: CustomFields::Source
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/custom_fields/source.rb
Defined Under Namespace
Modules: ClassMethods
Instance Method Summary collapse
-
#apply_custom_fields_diff(name) ⇒ Object
Apply the modifications collected from the custom fields by updating all the documents of the relation.
-
#apply_custom_fields_localize_diff(name) ⇒ Object
If the localized attribute has been changed in at least one of the custom fields, we have to upgrade all the records enhanced by custom_fields in order to make the values consistent with the mongoid localize option.
-
#bump_custom_fields_version(name) ⇒ Object
When the fields have been modified and before the object is saved, we bump the version.
-
#collect_custom_fields_diff(name, fields) ⇒ Array
Collects all the modifications of the custom fields.
-
#custom_fields_for?(name) ⇒ true, false
Determines if the relation is enhanced by the custom fields.
-
#custom_fields_recipe_for(name) ⇒ Array
Returns the recipe (meaning all the rules) needed to build the custom klass.
-
#custom_fields_version(name) ⇒ Integer
Returns the number of the version for relation with custom fields.
-
#initialize_custom_fields_diff(name) ⇒ Object
Initializes the object tracking the modifications of the custom fields.
-
#klass_with_custom_fields(name) ⇒ Class
Returns the class enhanced by the custom fields.
-
#ordered_custom_fields(name) ⇒ Collection
Returns the ordered list of custom fields for a relation.
-
#refresh_metadata_with_custom_fields(name) ⇒ Object
Change the metadata of a relation enhanced by the custom fields.
- #set_attribute_localization(name) ⇒ Object
Instance Method Details
#apply_custom_fields_diff(name) ⇒ Object
Apply the modifications collected from the custom fields by updating all the documents of the relation. The update uses the power of mongodb to make it fully optimized.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/custom_fields/source.rb', line 168 def apply_custom_fields_diff(name) # puts "==> apply_custom_fields_recipes for #{name}, #{self._custom_fields_diff[name].inspect}" # DEBUG operations = self._custom_fields_diff[name] operations['$set'].merge!({ 'custom_fields_recipe.version' => self.custom_fields_version(name) }) collection, selector = self.send(name).collection, self.send(name).criteria.selector # http://docs.mongodb.org/manual/reference/method/db.collection.update/#update-parameter # The <update> document must contain only update operator expressions. %w(set unset rename).each do |operation_name| _fields = operations.delete("$#{operation_name}") next if _fields.empty? _operation = { "$#{operation_name}" => _fields } collection.find(selector).update_many _operation end end |
#apply_custom_fields_localize_diff(name) ⇒ Object
If the localized attribute has been changed in at least one of the custom fields, we have to upgrade all the records enhanced by custom_fields in order to make the values consistent with the mongoid localize option.
Ex: post.attributes = ‘Hello world’ => post.attributes = { en: ‘Hello world’ }
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/custom_fields/source.rb', line 195 def apply_custom_fields_localize_diff(name) return if self._custom_field_localize_diff[name].empty? self.send(name).all.each do |record| updates = {} # puts "[apply_custom_fields_localize_diff] processing: record #{record._id} / #{self._custom_field_localize_diff[name].inspect}" # DEBUG self._custom_field_localize_diff[name].each do |changes| if changes[:localized] value = record.read_attribute(changes[:field].to_sym) updates[changes[:field]] = { Mongoid::Fields::I18n.locale.to_s => value } else # the other way around value = record.read_attribute(changes[:field].to_sym) next if value.nil? updates[changes[:field]] = value[Mongoid::Fields::I18n.locale.to_s] end end next if updates.empty? collection = self.send(name).collection collection.find(record.atomic_selector).update_one({ '$set' => updates }) end end |
#bump_custom_fields_version(name) ⇒ Object
When the fields have been modified and before the object is saved, we bump the version.
88 89 90 91 |
# File 'lib/custom_fields/source.rb', line 88 def bump_custom_fields_version(name) version = self.custom_fields_version(name) + 1 self.send(:"#{name}_custom_fields_version=", version) end |
#collect_custom_fields_diff(name, fields) ⇒ Array
Collects all the modifications of the custom fields
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/custom_fields/source.rb', line 145 def collect_custom_fields_diff(name, fields) # puts "==> collect_custom_fields_diff for #{name}, #{fields.size}" # DEBUG memo = self.initialize_custom_fields_diff(name) fields.map do |field| field.collect_diff(memo) end # collect fields with a modified localized field fields.each do |field| if field.localized_changed? && field.persisted? self._custom_field_localize_diff[name] << { field: field.name, localized: field.localized? } end end end |
#custom_fields_for?(name) ⇒ true, false
Determines if the relation is enhanced by the custom fields
24 25 26 |
# File 'lib/custom_fields/source.rb', line 24 def custom_fields_for?(name) self.class.custom_fields_for?(name) end |
#custom_fields_recipe_for(name) ⇒ Array
Returns the recipe (meaning all the rules) needed to build the custom klass
64 65 66 67 68 69 70 71 |
# File 'lib/custom_fields/source.rb', line 64 def custom_fields_recipe_for(name) { 'name' => "#{self.relations[name.to_s].class_name.demodulize}#{self._id}", 'rules' => self.ordered_custom_fields(name).map(&:to_recipe), 'version' => self.custom_fields_version(name), 'model_name' => self.relations[name.to_s].class_name.constantize.model_name.to_s } end |
#custom_fields_version(name) ⇒ Integer
Returns the number of the version for relation with custom fields
79 80 81 |
# File 'lib/custom_fields/source.rb', line 79 def custom_fields_version(name) self.send(:"#{name}_custom_fields_version") || 0 end |
#initialize_custom_fields_diff(name) ⇒ Object
Initializes the object tracking the modifications of the custom fields
132 133 134 135 136 137 |
# File 'lib/custom_fields/source.rb', line 132 def initialize_custom_fields_diff(name) self._custom_field_localize_diff ||= Hash.new([]) self._custom_fields_diff ||= {} self._custom_fields_diff[name] = { '$set' => {}, '$unset' => {}, '$rename' => {} } end |
#klass_with_custom_fields(name) ⇒ Class
Returns the class enhanced by the custom fields. Be careful, call this method only if the source class has been saved with success.
36 37 38 39 40 41 42 |
# File 'lib/custom_fields/source.rb', line 36 def klass_with_custom_fields(name) # Rails.logger.debug "[CustomFields] klass_with_custom_fields #{self.send(name).metadata.klass} / #{self.send(name).metadata[:old_klass]}" if defined?(Rails) # DEBUG recipe = self.custom_fields_recipe_for(name) = self.send(name). target = [:original_klass] || .klass # avoid to use an already enhanced klass target.klass_with_custom_fields(recipe) end |
#ordered_custom_fields(name) ⇒ Collection
Returns the ordered list of custom fields for a relation
53 54 55 |
# File 'lib/custom_fields/source.rb', line 53 def ordered_custom_fields(name) self.send(:"#{name}_custom_fields").sort { |a, b| (a.position || 0) <=> (b.position || 0) } end |
#refresh_metadata_with_custom_fields(name) ⇒ Object
Change the metadata of a relation enhanced by the custom fields. In Mongoid, all the instances of a same document share the same metadata objects.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/custom_fields/source.rb', line 98 def (name) return if !self.persisted? || self.send(:"#{name}_custom_fields").blank? # do not generate a klass without all the information = self.send(name). # puts "old_metadata = #{old_metadata.klass.inspect} / #{old_metadata.object_id.inspect}" # DEBUG # puts "[CustomFields] refresh_metadata_with_custom_fields, #{name.inspect}, self = #{self.inspect}" self.send(name). = .clone.tap do || # Rails.logger.debug "[CustomFields] refresh_metadata_with_custom_fields #{metadata.klass}" if defined?(Rails) # DEBUG # backup the current klass [:original_klass] ||= .klass .instance_variable_set(:@klass, self.klass_with_custom_fields(name)) end set_attribute_localization(name) # puts "new_metadata = #{self.send(name).metadata.klass.inspect} / #{self.send(name).metadata.object_id.inspect}" # DEBUG end |
#set_attribute_localization(name) ⇒ Object
119 120 121 122 123 124 125 |
# File 'lib/custom_fields/source.rb', line 119 def set_attribute_localization(name) klass_name = name.singularize.to_sym self.send(:"#{name}_custom_fields").each do |cf| I18n.backend.store_translations ::I18n.locale, {mongoid: { attributes: {klass_name => {cf.name.to_sym => cf.label}}}} end end |