foreman/app/models/concerns/has_many_common.rb @ d7c67746
3b656b8d | Joseph Mitchell Magen | module HasManyCommon
|
|
extend ActiveSupport::Concern
|
|||
def assoc_klass(association)
|
|||
1cf860b7 | Stephen Benjamin | self.class.reflect_on_association(association).klass
|
|
3b656b8d | Joseph Mitchell Magen | end
|
|
832c0925 | Joseph Magen | # calls method :name or whatever is defined in attr_name :title
|
|
3b656b8d | Joseph Mitchell Magen | 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
|
|||
4f7a4d0b | David Davis | def has_name?(field = "name")
|
|
3b656b8d | Joseph Mitchell Magen | self.column_names.include?(field)
|
|
end
|
|||
# class method in model to overwrite default attribute_name
|
|||
# Ex.
|
|||
# Class Hostgroup
|
|||
832c0925 | Joseph Magen | # attr_name :title
|
|
3b656b8d | Joseph Mitchell Magen | 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 ####
|
|||
fb9f45e8 | Daniel Lobato | def has_many(*args)
|
|
options = args.last.is_a?(Hash) ? args.last : {}
|
|||
has_many_names_for(args.first, options)
|
|||
3b656b8d | Joseph Mitchell Magen | 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
|
|||
9e892b43 | Tomer Brisker | self.send(association).map(&:name_method)
|
|
3b656b8d | Joseph Mitchell Magen | end
|
|
end
|
|||
#### belongs_to ####
|
|||
fb9f45e8 | Daniel Lobato | def belongs_to(*args)
|
|
options = args.last.is_a?(Hash) ? args.last : {}
|
|||
belongs_to_name_for(args.first, options)
|
|||
3b656b8d | Joseph Mitchell Magen | super
|
|
end
|
|||
def belongs_to_name_for(association, options)
|
|||
assoc = association.to_s.tableize.singularize
|
|||
7c671609 | Dominic Cleal | assoc_name = options.delete(:name_accessor) || "#{assoc}_name"
|
|
3b656b8d | Joseph Mitchell Magen | ||
# SETTER _name= method
|
|||
7c671609 | Dominic Cleal | define_method "#{assoc_name}=" do |name_value|
|
|
65af0932 | Shlomi Zadok | assoc_id = assoc_klass(association).send("find_by_#{assoc_klass(association).attribute_name}", name_value).try(:id)
|
|
d7c67746 | Michael Moll | unless assoc_id
|
|
raise Foreman::AssociationNotFound
|
|||
.new(_("Could not find %{association} with name: %{name}") % { name: name_value, association: association })
|
|||
end
|
|||
3b656b8d | Joseph Mitchell Magen | self.send("#{assoc}_id=", assoc_id)
|
|
end
|
|||
# GETTER _name method
|
|||
7c671609 | Dominic Cleal | define_method assoc_name do
|
|
9e892b43 | Tomer Brisker | self.send(association).try(:name_method)
|
|
3b656b8d | Joseph Mitchell Magen | end
|
|
end
|
|||
end
|
|||
end
|