Project

General

Profile

Download (2.76 KB) Statistics
| Branch: | Tag: | Revision:
module HasManyCommon
extend ActiveSupport::Concern

def assoc_klass(association)
self.class.reflect_on_association(association).klass
end

# calls method :name or whatever is defined in attr_name :title
def name_method
send(self.class.attribute_name)
end

module ClassMethods
# default attribute used by *_names and *_name is :name
# if :name doesn't exist, :id is used, so it doesn't error out if attr_name :field is not defined
# most likely model will have attr_name :field to overwrite attribute_name
def attribute_name
if has_name?
:name
else
:id
end
end

def has_name?(field = "name")
self.column_names.include?(field)
end

# class method in model to overwrite default attribute_name
# Ex.
# Class Hostgroup
# attr_name :title
def attr_name(attribute)
self_class.send(:define_method, "attribute_name") do
attribute
end
end

def self_class
class << self; self end
end

#### has_many ####
def has_many(*args)
options = args.last.is_a?(Hash) ? args.last : {}
has_many_names_for(args.first, options)
super
end

def has_and_belongs_to_many(association, options = {})
has_many_names_for(association, options)
super
end

def has_many_names_for(association, options)
assoc = association.to_s.tableize.singularize

# SETTER _names= method
define_method "#{assoc}_names=" do |name_values|
ids = Array.wrap(name_values).map do |name_value|
assoc_klass(association).send("find_by_#{assoc_klass(association).attribute_name}", name_value).id
end
self.send("#{assoc}_ids=", ids)
end

# GETTER _names method
define_method "#{assoc}_names" do
self.send(association).map(&:name_method)
end
end

#### belongs_to ####
def belongs_to(*args)
options = args.last.is_a?(Hash) ? args.last : {}
belongs_to_name_for(args.first, options)
super
end

def belongs_to_name_for(association, options)
assoc = association.to_s.tableize.singularize
assoc_name = options.delete(:name_accessor) || "#{assoc}_name"

# SETTER _name= method
define_method "#{assoc_name}=" do |name_value|
assoc_id = assoc_klass(association).send("find_by_#{assoc_klass(association).attribute_name}", name_value).try(:id)
unless assoc_id
raise Foreman::AssociationNotFound
.new(_("Could not find %{association} with name: %{name}") % { name: name_value, association: association })
end
self.send("#{assoc}_id=", assoc_id)
end

# GETTER _name method
define_method assoc_name do
self.send(association).try(:name_method)
end
end
end
end
(18-18/46)