| Module | ActiveRecord::Acts::EavModel::InstanceMethods |
| In: |
lib/acts_as_eav_model.rb
|
Return a list of valid eav attributes for the given model. Return nil if any field is allowed. If you want to say no field is allowed then return an empty array. If you just have a static list the :fields option is most likely easier.
# File lib/acts_as_eav_model.rb, line 347
347: def eav_attributes(model); nil end
Will determine if the given attribute is a eav attribute on the given model. Override this in your class to provide custom logic if the eav_attributes method or the :fields option are not flexible enough. If you override this method :fields and eav_attributes will not apply at all unless you implement them yourself.
# File lib/acts_as_eav_model.rb, line 332
332: def is_eav_attribute?(attribute_name, model)
333: attribute_name = attribute_name.to_s
334: model_options = eav_options[model.name]
335: return model_options[:fields].include?(attribute_name) unless model_options[:fields].nil?
336: return eav_attributes(model).collect {|field| field.to_s}.include?(attribute_name) unless
337: eav_attributes(model).nil?
338: true
339: end
yields for each eav relation.
# File lib/acts_as_eav_model.rb, line 473
473: def each_eav_relation
474: eav_options.keys.each {|kls| yield kls.constantize}
475: end
Retrieve the collection of related eav attributes
# File lib/acts_as_eav_model.rb, line 453
453: def eav_related(model)
454: relationship = eav_options[model.name][:relationship_name]
455: send relationship
456: end
yield only if attribute_name is a eav_attribute
# File lib/acts_as_eav_model.rb, line 461
461: def exec_if_related(attribute_name)
462: return false if self.class.column_names.include?(attribute_name)
463: each_eav_relation do |model|
464: if is_eav_attribute?(attribute_name, model)
465: yield model
466: end
467: end
468: end
Retrieve the related eav attribute object
# File lib/acts_as_eav_model.rb, line 443
443: def find_related_eav_attribute(model, attribute_name)
444: name_field = eav_options[model.name][:name_field]
445: eav_related(model).to_a.find do |relation|
446: relation.send(name_field) == attribute_name
447: end
448: end
Implements eav-attributes as if real getter/setter methods were defined.
# File lib/acts_as_eav_model.rb, line 424
424: def method_missing_with_eav_behavior(method_id, *args, &block)
425: begin
426: method_missing_without_eav_behavior(method_id, *args, &block)
427: rescue NoMethodError => e
428: attribute_name = method_id.to_s.sub(/\=$/, '')
429: exec_if_related(attribute_name) do |model|
430: if method_id.to_s =~ /\=$/
431: return write_attribute_with_eav_behavior(attribute_name, args[0])
432: else
433: return read_attribute_with_eav_behavior(attribute_name)
434: end
435: end
436: raise e
437: end
438: end
Overrides ActiveRecord::Base#read_attribute
# File lib/acts_as_eav_model.rb, line 375
375: def read_attribute_with_eav_behavior(attribute_name)
376: attribute_name = attribute_name.to_s
377: exec_if_related(attribute_name) do |model|
378: return nil if !@remove_eav_attr.nil? && @remove_eav_attr.any? do |r|
379: r[0] == model && r[1] == attribute_name
380: end
381:
382: value_field = eav_options[model.name][:value_field]
383: related_attribute = find_related_eav_attribute(model, attribute_name)
384:
385: return nil if related_attribute.nil?
386: return related_attribute.send(value_field)
387: end
388: read_attribute_without_eav_behavior(attribute_name)
389: end
Called after validation on update so that eav attributes behave like normal attributes in the fact that the database is not touched until save is called.
# File lib/acts_as_eav_model.rb, line 356
356: def save_modified_eav_attributes
357: return if @save_eav_attr.nil?
358: @save_eav_attr.each do |s|
359: model, attribute_name = s
360: related_attribute = find_related_eav_attribute(model, attribute_name)
361: unless related_attribute.nil?
362: if related_attribute.value.nil?
363: eav_related(model).delete(related_attribute)
364: else
365: related_attribute.save
366: end
367: end
368: end
369: @save_eav_attr = []
370: end
Overrides ActiveRecord::Base#write_attribute
# File lib/acts_as_eav_model.rb, line 394
394: def write_attribute_with_eav_behavior(attribute_name, value)
395: attribute_name = attribute_name.to_s
396: exec_if_related(attribute_name) do |model|
397: value_field = eav_options[model.name][:value_field]
398: @save_eav_attr ||= []
399: @save_eav_attr << [model, attribute_name]
400: related_attribute = find_related_eav_attribute(model, attribute_name)
401: if related_attribute.nil?
402: # Used to check for nil? but this caused validation
403: # problems that are harder to solve. blank? is probably
404: # not correct but it works well for now.
405: unless value.blank?
406: name_field = eav_options[model.name][:name_field]
407: foreign_key = eav_options[model.name][:foreign_key]
408: eav_related(model).build name_field => attribute_name,
409: value_field => value, foreign_key => self.id
410: end
411: return value
412: else
413: value_field = (value_field.to_s + '=').to_sym
414: return related_attribute.send(value_field, value)
415: end
416: end
417: write_attribute_without_eav_behavior(attribute_name, value)
418: end