Revision 943bc1a2
Added by Ondřej Pražák almost 6 years ago
app/models/concerns/taxonomy_collision_finder.rb | ||
---|---|---|
module TaxonomyCollisionFinder
|
||
extend ActiveSupport::Concern
|
||
|
||
module ClassMethods
|
||
def find_without_collision(attribute, value)
|
||
from_local = find_or_initialize_by attribute => value
|
||
from_global = unscoped.find_or_initialize_by attribute => value
|
||
from_local.errors.add(attribute, _("cannot be used, please choose another")) if from_local.new_record? && from_global.persisted?
|
||
from_local
|
||
end
|
||
end
|
||
end
|
app/models/provisioning_template.rb | ||
---|---|---|
friendly_id :name
|
||
include Parameterizable::ByIdName
|
||
include DirtyAssociations
|
||
include TaxonomyCollisionFinder
|
||
|
||
class << self
|
||
# we have to override the base_class because polymorphic associations does not detect it correctly, more details at
|
app/models/ptable.rb | ||
---|---|---|
include Parameterizable::ByIdName
|
||
include ValidateOsFamily
|
||
include DirtyAssociations
|
||
include TaxonomyCollisionFinder
|
||
|
||
class << self
|
||
# we have to override the base_class because polymorphic associations does not detect it correctly, more details at
|
app/models/template.rb | ||
---|---|---|
# based on +name it either finds existing template or builds a new one
|
||
# then it applies changes to it and return this object, note no changes were saved at this point
|
||
def self.import_without_save(name, text, options = {})
|
||
template = self.unscoped.find_or_initialize_by(:name => name)
|
||
template = self.find_without_collision :name, name
|
||
Foreman::Logging.logger('app').debug "#{template.new_record? ? 'building new' : 'updating existing'} template"
|
||
template.import_without_save(text, options)
|
||
end
|
||
... | ... | |
# :default - default flag value (false by default)
|
||
def self.import!(name, text, options = {})
|
||
template = import_without_save(name, text, options)
|
||
return template unless template.valid?
|
||
if options[:force]
|
||
template.ignore_locking { template.save! }
|
||
else
|
||
... | ... | |
template
|
||
end
|
||
|
||
# override in subclass to handle taxonomy scope, see TaxonomyCollisionFinder
|
||
def self.find_without_collision(attribute, name)
|
||
self.find_or_initialize_by :name => name
|
||
end
|
||
|
||
private
|
||
|
||
# This method can be overridden in Template children classes to import additional attributes
|
test/models/template_test.rb | ||
---|---|---|
describe '.import!' do
|
||
test 'by default it does not ignore locking' do
|
||
template = Minitest::Mock.new
|
||
template.expect(:valid?, true)
|
||
template.expect(:save!, true)
|
||
Template.expects(:import_without_save => template)
|
||
Template.import!('test', '')
|
||
... | ... | |
|
||
test 'locking can be overriden by force option' do
|
||
template = Minitest::Mock.new
|
||
template.expect(:valid?, true)
|
||
template.expect(:ignore_locking, true)
|
||
Template.expects(:import_without_save => template)
|
||
Template.import!('test', '', { :force => true })
|
||
... | ... | |
refute_includes @template.operatingsystem_ids, @os2.id
|
||
end
|
||
end
|
||
|
||
describe '::find_without_name_collision in subclasses' do
|
||
setup do
|
||
@org = FactoryBot.create(:organization, :name => 'TemplateOrg')
|
||
@empty = FactoryBot.create(:organization, :name => 'EmptyOrg')
|
||
@regular_template = FactoryBot.create(:provisioning_template, :name => 'regular template', :organizations => [@org])
|
||
@collision_template = FactoryBot.create(:provisioning_template, :name => 'collision template', :organizations => [@empty])
|
||
@common_template = FactoryBot.create(:provisioning_template, :name => 'common template', :organizations => [@empty, @org])
|
||
@before_org = Organization.current
|
||
Organization.current = @org
|
||
end
|
||
|
||
test 'should initialize a new template' do
|
||
template = ProvisioningTemplate.find_without_collision(:name, 'new template')
|
||
assert template.new_record?
|
||
assert template.errors.empty?
|
||
end
|
||
|
||
test 'should return existing template in current context' do
|
||
assert_equal @regular_template, ProvisioningTemplate.find_without_collision(:name, 'regular template')
|
||
end
|
||
|
||
test 'should return existing template if persent in multiple contexts' do
|
||
assert_equal @common_template, ProvisioningTemplate.find_without_collision(:name, 'common template')
|
||
end
|
||
|
||
test 'should return new instance with error when outside of current context' do
|
||
template = ProvisioningTemplate.find_without_collision(:name, 'collision template')
|
||
assert template.new_record?
|
||
refute template.errors.empty?
|
||
assert_equal "cannot be used, please choose another", template.errors.messages[:name].first
|
||
end
|
||
end
|
||
end
|
||
end
|
Also available in: Unified diff
Fixes #23994 - Do not update templates out of scope