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

Evaluate visibility expressions for CustomButtons #15725

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/models/custom_button.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ def evaluate_enablement_expression_for(object)
enablement_expression.lenient_evaluate(object)
end

def evaluate_visibility_expression_for(object)
return true unless visibility_expression
return false if visibility_expression && !object # object == nil, method is called for list of objects
visibility_expression.lenient_evaluate(object)
end

# End - Helper methods to support moving automate columns to resource_actions table

def self.parse_uri(uri)
Expand Down
35 changes: 35 additions & 0 deletions app/models/custom_button_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,41 @@ def self.applies_to_all_instances(class_name)
applies_to_class(class_name).where("set_data not like ?", "%:applies_to_id%")
end

# Params:
# custom_button_sets: <Array>CustomButtonSet
# object: for this object are evaluated visibility_expression of CustomButtons
# one CustomButtonSet contains any CustomButtons,
# CustomButtonSet has stored this ids of CustomButtons in array CustomButton#set_data[:button_order]
# Returns:
# <Array>CustomButtonSet
#
# example:
# let's have:
# custom_buttons_set =
# <Array> [<CustomButtonSet> id: 10000000000075,
# set_data:
# {:button_order=> [1, 2]}, list ids of custom buttons in custom button set (group of buttons in UI)
# ... ]
# object = Vm.first
#
# then CustomButtonSet.filter_with_visibility_expression(custom_button_sets, object) returns:
# - same custom_button_sets array when all visibility expressions are not populated(CustomButton#visibility_expression = nil)
# - same custom_button_sets array but with filtered list custom buttons ids in each custom button set from
# custom_button_sets when any visibility expression is evaluated to true
# - ids of custom buttons with visibility expression which are evaluated to false are removed from CustomButtonSet#set_data[:button_order]
# - filtered custom_button_sets array when all visibilty expression custom buttons have been evaluated to false
def self.filter_with_visibility_expression(custom_button_sets, object)
custom_button_sets.each_with_object([]) do |custom_button_set, ret|
custom_button_from_set = CustomButton.where(:id => custom_button_set.set_data[:button_order]).select(:id, :visibility_expression)
filtered_ids = custom_button_from_set.select { |x| x.evaluate_visibility_expression_for(object) }.pluck(:id)
if filtered_ids.present?
custom_button_set.set_data[:button_order] = filtered_ids
ret << custom_button_set
end
ret
end
end

def deep_copy(options)
raise ArgumentError, "options[:owner] is required" if options[:owner].blank?

Expand Down
34 changes: 34 additions & 0 deletions spec/models/custom_button_set_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,40 @@
end
end

describe '.filter_with_visibility_expression' do
let(:vm_1) { FactoryGirl.create(:vm_vmware, :name => 'vm_1') }
let(:custom_button_1) { FactoryGirl.create(:custom_button, :applies_to => vm_1) }
let(:miq_expression) { MiqExpression.new('EQUAL' => {'field' => 'Vm-name', 'value' => "vm_1"}) }
let(:custom_button_2) { FactoryGirl.create(:custom_button, :applies_to => vm_1, :visibility_expression => miq_expression) }
let(:set_data) { {:applies_to_class => "Vm", :button_order => [custom_button_1.id, custom_button_2.id]} }
let(:custom_button_set) { FactoryGirl.create(:custom_button_set, :name => "set_1", :set_data => set_data) }

context 'when all CustomButtons#visibility_expression=nil' do
let(:miq_expression) { nil }

it 'returns same array CustomButtonSet as input' do
expect(described_class.filter_with_visibility_expression([custom_button_set], vm_1)).to eq([custom_button_set])
end
end

context 'when any visibility_expression is evaluated to false and any to true' do
let(:miq_expression_false) { MiqExpression.new('EQUAL' => {'field' => 'Vm-name', 'value' => "vm_2"}) }
let(:custom_button_1) { FactoryGirl.create(:custom_button, :applies_to => vm_1, :visibility_expression => miq_expression_false) }

it 'returns filtered array of CustomButtonSet and CustomButtons' do
set = described_class.filter_with_visibility_expression([custom_button_set], vm_1).first
expect(set.set_data[:button_order]).to eq([custom_button_2.id])
end

context 'all CustomButtons#visibility_expression are evaluated to false' do
let(:miq_expression) { MiqExpression.new('EQUAL' => {'field' => 'Vm-name', 'value' => 'vm_2'}) }
it 'returns empty array of CustomButtonSet' do
expect(described_class.filter_with_visibility_expression([custom_button_set], vm_1)).to be_empty
end
end
end
end

it "#deep_copy" do
service_template1 = FactoryGirl.create(:service_template)
service_template2 = FactoryGirl.create(:service_template)
Expand Down