Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CustomButtonSet - make sure children follow button_order #18368

Merged
merged 7 commits into from
Mar 7, 2019
20 changes: 20 additions & 0 deletions app/models/custom_button_set.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
class CustomButtonSet < ApplicationRecord
acts_as_miq_set

before_save :validate_children
after_save :update_children

def validate_children
return if set_data.try(:[], :button_order).nil?

children = Rbac.filtered(CustomButton.where(:id => set_data[:button_order]))
throw(:abort) if children.pluck(:id).sort != set_data[:button_order].sort
end

def update_children
if set_data.try(:[], :button_order).nil?
remove_all_children
return
end

children = Rbac.filtered(CustomButton.where(:id => set_data[:button_order]))
replace_children(children)
end

def self.find_all_by_class_name(class_name, class_id = nil)
ordering = ->(o) { [o.set_data[:group_index].to_s, o.name] }

Expand Down
17 changes: 9 additions & 8 deletions lib/task_helpers/imports/custom_buttons.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ def create_object(class_name, obj_array)
klass = class_name.camelize.constantize

obj_array.collect do |obj|
begin
klass.create!(obj['attributes']&.except('guid')).tap do |new_obj|
add_children(obj, new_obj)
add_associations(obj, new_obj)
try("#{class_name}_post", new_obj)
end
rescue StandardError
raise
if klass.name == "CustomButtonSet"
order = obj.fetch_path('attributes', 'set_data', :button_order)
obj['attributes']['set_data'][:button_order] = nil if order.present?
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a red flag for @martinpovolny, but I understand that we need something like this 😕

Copy link
Contributor Author

@himdel himdel Jan 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, none of CustomButtonSet === klass, klass.is_a? CustomButtonSet, klass.kind_of? ::CustomButtonSet are true, only string comparison works.

And that "custom button" import deals with 3 different types of entities (CustomButton, CustomButtonSet, and ResourceAction for some reason).

But yeah, I don't like it either :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems really weird. Have you inspected the klass variable to see why that would happen? What does klass.class show?

Copy link
Contributor Author

@himdel himdel Jan 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@djberg96

> klass
=> CustomButtonSet(id: integer, name: string, description: string, set_type: string, created_on: datetime, updated_on: datetime, guid: string, read_only: boolean, set_data: text, mode: string, owner_type: string, owner_id: integer, userid: string, group_id: integer, href_slug: string, region_number: integer, region_description: string)

> klass.class
=> Class

> klass.name
=> "CustomButtonSet"

> CustomButtonSet
=> CustomButtonSet(id: integer, name: string, description: string, set_type: string, created_on: datetime, updated_on: datetime, guid: string, read_only: boolean, set_data: text, mode: string, owner_type: string, owner_id: integer, userid: string, group_id: integer, href_slug: string, region_number: integer, region_description: string)

> CustomButtonSet.class
=> Class

> CustomButtonSet.name
=> "CustomButtonSet"

> klass.is_a? CustomButtonSet
=> false

> CustomButtonSet.is_a? klass
=> false

¯\_(ツ)_/¯

Copy link
Contributor Author

@himdel himdel Jan 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fun :)

> klass.object_id
=> 47105247798240

> CustomButtonSet.object_id
=> 47105247798240

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this could be caused by FactoryGirl, I'm running this via be rspec spec/lib/task_helpers/imports/custom_buttons_spec.rb

Copy link
Contributor

@djberg96 djberg96 Jan 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean FactoryBot? ;)

Anyway, I've been burned a few times by FactoryBot creating new instances internally, causing allow to fail. I'll have to look at the spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heheh, I actually don't think being a girl should be considered offensive :). But yeah, that.

Thanks! :)


klass.create!(obj['attributes']&.except('guid')).tap do |new_obj|
add_children(obj, new_obj)
add_associations(obj, new_obj)
try("#{class_name}_post", new_obj)
end
end
end
Expand Down
24 changes: 24 additions & 0 deletions spec/models/custom_button_set_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,28 @@
expect(CustomButton.count).to eq(2)
expect(CustomButtonSet.count).to eq(2)
end

context '#update_children' do
let(:vm) { FactoryBot.create(:vm_vmware, :name => 'vm') }
let(:custom_button_1) { FactoryBot.create(:custom_button, :applies_to => vm) }
let(:custom_button_2) { FactoryBot.create(:custom_button, :applies_to => vm) }
let(:custom_button_3) { FactoryBot.create(:custom_button, :applies_to => vm) }
let(:set_data) { {:applies_to_class => "Vm", :button_order => [custom_button_1.id, custom_button_2.id]} }
let(:custom_button_set) { FactoryBot.create(:custom_button_set, :name => "set_1", :set_data => set_data) }

it "updates children after setting button_order" do
expect(custom_button_set.children.count).to eq(2)

custom_button_set.set_data[:button_order] = [
custom_button_2.id,
custom_button_3.id,
]
custom_button_set.save!

expect(custom_button_set.children.count).to eq(2)
expect(custom_button_set.children).not_to include(custom_button_1)
expect(custom_button_set.children).to include(custom_button_2)
expect(custom_button_set.children).to include(custom_button_3)
end
end
end
6 changes: 2 additions & 4 deletions spec/models/generic_object_definition_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,7 @@
it "returns the custom actions in a hash grouped by buttons and button groups" do
FactoryBot.create(:custom_button, :name => "generic_no_group", :applies_to_class => "GenericObject")
generic_group = FactoryBot.create(:custom_button, :name => "generic_group", :applies_to_class => "GenericObject")
generic_group_set = FactoryBot.create(:custom_button_set, :name => "generic_group_set")
generic_group_set.add_member(generic_group)
generic_group_set = FactoryBot.create(:custom_button_set, :name => "generic_group_set", :set_data => {:button_order => [generic_group.id]})

FactoryBot.create(
:custom_button,
Expand All @@ -312,8 +311,7 @@
:applies_to_class => "GenericObjectDefinition",
:applies_to_id => definition.id
)
assigned_group_set = FactoryBot.create(:custom_button_set, :name => "assigned_group_set")
assigned_group_set.add_member(assigned_group)
assigned_group_set = FactoryBot.create(:custom_button_set, :name => "assigned_group_set", :set_data => {:button_order => [assigned_group.id]})
definition.update(:custom_button_sets => [assigned_group_set])

expected = {
Expand Down
7 changes: 5 additions & 2 deletions spec/models/service_template_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
FactoryBot.create(:custom_button, :name => "generic_no_group", :applies_to_class => "Service")
generic_group = FactoryBot.create(:custom_button, :name => "generic_group", :applies_to_class => "Service")
generic_group_set = FactoryBot.create(:custom_button_set, :name => "generic_group_set")
generic_group_set.add_member(generic_group)
generic_group_set.set_data = {:button_order => [generic_group.id]}
generic_group_set.save!

service_template = FactoryBot.create(:service_template)
FactoryBot.create(
Expand All @@ -24,7 +25,9 @@
:applies_to_id => service_template.id
)
assigned_group_set = FactoryBot.create(:custom_button_set, :name => "assigned_group_set")
assigned_group_set.add_member(assigned_group)
assigned_group_set.set_data = {:button_order => [assigned_group.id]}
assigned_group_set.save!

service_template.update(:custom_button_sets => [assigned_group_set])

expected = {
Expand Down