Skip to content

Commit

Permalink
Run GHA on Ruby 3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ofedoren committed Jan 10, 2024
1 parent 6575dc0 commit fde7cd8
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .github/matrix.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"postgresql": ["12"],
"ruby": ["2.7"],
"ruby": ["2.7", "3.0"],
"node": ["14"]
}
6 changes: 3 additions & 3 deletions app/models/concerns/foreman/sti.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ class << base

module ClassMethods
# ensures that the correct STI object is created when :type is passed.
def new(*attributes, &block)
if (h = attributes.first).is_a?(Hash) && (type = h.with_indifferent_access.delete(:type)) && !type.empty?
def new(attributes = nil, &block)
if attributes.is_a?(Hash) && (type = attributes.with_indifferent_access.delete(:type)) && !type.empty?
if (klass = type.constantize) != self
raise "Invalid type #{type}" unless klass <= self
return klass.new(*attributes, &block)
return klass.new(attributes, &block)
end
end

Expand Down
41 changes: 36 additions & 5 deletions app/models/host.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
module Host
def self.method_missing(method, *args, &block)
def self.method_missing(method, *args, **kwargs, &block)
type = "Host::Managed"
case method.to_s
when /create/, 'new'
# in this case args should contain a hash with host attributes
if args.empty? || args[0].nil? # got no parameters
# set the default type
args = [{:type => type}]
else # got some parameters
args[0][:type] ||= type # adds the type if it doesn't exists
type = args[0][:type] # stores the type for later usage.
end
end
if type.constantize.respond_to?(method, true)
type.constantize.send(method, *args, &block)
type.constantize.send(method, kwargs.merge(args.first), &block) # quick skip for simple cases
else
super
klass = type.constantize
if klass.respond_to?(method, true)
# Removing block, since we will pass it anyway
meth_params = klass.method(method).parameters.collect { |par_desc| par_desc.first } - [:block]
if meth_params.empty? || (args.empty? && kwargs.empty?)
klass.send(method, &block)
elsif meth_params == [:rest]
# means that the method could accept anything, e.g. def find_by(*args),
# but internally would expect a Hash wrapped by *args array
# or there are cases like Array#last, which has * as param list, but expects an Integer
# since there is a lot of delegation in Rails, it's hard to know exact signature of the real method:
# find_in_batches expects only kwargs, but method(:find_in_batces) returns (*) as param list
# through the same delegation goes find_by with a different signature/expectations

if !args.empty?
klass.send(method, *args, &block)
elsif kwargs.any?
klass.send(method, **kwargs, &block)
# here should probably be a closing "else" for other cases
end
elsif (meth_params & [:req, :opt, :rest]).empty?
# this would mean we pass kwargs only
klass.send(method, **kwargs, &block)
elsif (meth_params & [:key, :keyreq, :keyrest]).empty?
# if there is no kwargs, let's treat this as before
klass.send(method, *args, &block)
else
# let's treat as we should
klass.send(method, *args, **kwargs, &block)
end
else
super
end
end
end

Expand Down
23 changes: 11 additions & 12 deletions app/models/host/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@ def self.taxonomy_conditions
# initializer and we set name when we are sure that we have primary interface
# we can't create primary interface before calling super because args may contain nested
# interface attributes
def initialize(*args)
def initialize(attributes = nil, &block)
values_for_primary_interface = {}
build_values_for_primary_interface!(values_for_primary_interface, args)
attributes = attributes&.with_indifferent_access
build_values_for_primary_interface!(values_for_primary_interface, attributes)

super(*args)
super(attributes, &block)

build_required_interfaces
update_primary_interface_attributes(values_for_primary_interface)
Expand Down Expand Up @@ -401,19 +402,17 @@ def parse_ip_address(address, ignore_link_local: true)
addr.to_s
end

def build_values_for_primary_interface!(values_for_primary_interface, args)
new_attrs = args.shift
unless new_attrs.nil?
new_attrs = new_attrs.with_indifferent_access
values_for_primary_interface[:name] = NameGenerator.new.next_random_name unless new_attrs.has_key?(:name)
def build_values_for_primary_interface!(values_for_primary_interface, attributes)
unless attributes.nil?
values_for_primary_interface[:name] = NameGenerator.new.next_random_name unless attributes.has_key?(:name)
PRIMARY_INTERFACE_ATTRIBUTES.each do |attr|
values_for_primary_interface[attr] = new_attrs.delete(attr) if new_attrs.has_key?(attr)
values_for_primary_interface[attr] = attributes.delete(attr) if attributes.has_key?(attr)
end

model_name = new_attrs.delete(:model_name)
new_attrs[:hardware_model_name] = model_name if model_name.present?
model_name = attributes.delete(:model_name)
attributes[:hardware_model_name] = model_name if model_name.present?

args.unshift(new_attrs)
attributes
end
end

Expand Down
5 changes: 2 additions & 3 deletions app/models/host/managed.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,8 @@ def self.complete_for(query, opts = {})

include PxeLoaderValidator

def initialize(*args)
args.unshift(apply_inherited_attributes(args.shift, false))
super(*args)
def initialize(attributes = nil, &block)
super(apply_inherited_attributes(attributes, false), &block)
end

def build_hooks
Expand Down
6 changes: 3 additions & 3 deletions app/models/subnet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,9 @@ def subnet_for(ip)
end

# This casts Subnet to Subnet::Ipv4 if no type is set
def new(*attributes, &block)
type = attributes.first.with_indifferent_access.delete(:type) if attributes.first.is_a?(Hash)
return Subnet::Ipv4.new(*attributes, &block) if self == Subnet && type.nil?
def new(attributes = nil, &block)
type = attributes.with_indifferent_access.delete(:type) if attributes.is_a?(Hash)
return Subnet::Ipv4.new(attributes, &block) if self == Subnet && type.nil?
super
end

Expand Down
4 changes: 2 additions & 2 deletions test/helpers/application_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ def test_generate_link_for
end

test '#documentation_url and new docs page' do
url = documentation_url('TestSection', { type: 'plugin_manual', name: 'foreman_my_plugin', version: '1.2' })
url = documentation_url('TestSection', type: 'plugin_manual', name: 'foreman_my_plugin', version: '1.2')

assert_match %r{links/plugin_manual/TestSection\?name=foreman_my_plugin&version=1\.2}, url
end

test '#documentation_url and new docs page' do
url = documentation_url('TestSection', { type: 'docs', chapter: 'test_chapter' })
url = documentation_url('TestSection', type: 'docs', chapter: 'test_chapter')

assert_match %r{links/docs/TestSection\?chapter=test_chapter}, url
end
Expand Down

0 comments on commit fde7cd8

Please sign in to comment.