module ForemanPuppet class HostgroupPuppetFacet < ApplicationRecord # ------ ANCESTRY ATTRIBUTES ------- # This mimic nested attributes, that should probably be provided by Facets::HostgroupFacet class << self attr_reader :nested_attribute_fields def nested_attribute_for(*fields) @nested_attribute_fields ||= [] @nested_attribute_fields |= fields @nested_attribute_fields.each do |field| # Example method # def inherited_compute_profile_id # read_attribute(:compute_profile_id) || nested_compute_profile_id # end define_method "inherited_#{field}" do self[field] || nested(field) end # Example method - only override method generated by assocation if there is ancestry. # if ancestry.present? # def compute_profile # ComputeProfile.find_by_id(inherited_compute_profile_id) # end # end next unless (md = field.to_s.match(/(\w+)_id$/)) define_method md[1] do if hostgroup.ancestry.present? klass = "ForemanPuppet::#{md[1].classify}" klass = 'SmartProxy' if md[1] == 'puppet_proxy' || md[1] == 'puppet_ca_proxy' klass = 'Subnet::Ipv4' if md[1] == 'subnet' klass = 'Subnet::Ipv6' if md[1] == 'subnet6' klass.constantize.find_by(id: send("inherited_#{field}")) else # () is required. # Otherwise, get RuntimeError: implicit argument passing of super from method defined by define_method() is not supported. # Specify all arguments explicitly. super() end end end end end def nested(attr) return nil if hostgroup.ancestry.blank? Hostgroup.sort_by_ancestry(hostgroup.ancestors.joins(:puppet).where(HostgroupPuppetFacet.arel_table[attr.to_sym].not_eq(nil))).last&.puppet.try(attr) end delegate :parent_id, to: :hostgroup # and helpers def parent_facet_id parent_facet&.id end def parent_facet @parent_facet ||= hostgroup.parent_id && HostgroupPuppetFacet.find_by(hostgroup_id: hostgroup.parent_id) end # ------ END ANCESTRY ------- audited associated_with: :hostgroup self.table_name = 'hostgroup_puppet_facets' include ForemanPuppet::PuppetFacetCommon include Facets::HostgroupFacet has_many :hostgroup_classes, dependent: :destroy has_many :puppetclasses, through: :hostgroup_classes before_save :remove_duplicated_nested_class nested_attribute_for :environment_id def all_config_groups (config_groups + parent_config_groups).uniq end def parent_config_groups return [] unless hostgroup.parent groups = [] hostgroup.ancestors.each do |hostgroup| groups += hostgroup.puppet&.config_groups || [] end groups.uniq end # the environment used by #clases nees to be self.environment and not self.parent.environment def parent_classes return [] unless parent_facet parent_facet.classes(environment) end def remove_duplicated_nested_class ancestor_hgs = hostgroup.ancestors.preload(puppet: :puppetclasses) self.puppetclasses -= ancestor_hgs.map { |ancestor| ancestor.puppet&.puppetclasses }.compact.flatten end end end