From 518af3eb97cc9eee948929ec70f1d9b1dcb8fb6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Sun, 18 Sep 2022 17:51:18 +0200 Subject: [PATCH] Remove duplication in poll actions tables We were using the same logic in four different places, so we're creating a new class to handle that logic. Note that I didn't find a way to delegate the `content` method to a `Admin::TableActionsComponent`, so we're delegating the `action` method instead. That means we need to create a method returning an `Admin::TableActionsComponent`. We also need to cache this object; otherwise we were getting an error when calling `actions.action` from the `Admin::Poll::Questions::TableActionsComponent`. --- .../allowed_table_actions_component.html.erb | 3 + .../admin/allowed_table_actions_component.rb | 20 +++++++ .../table_actions_component.html.erb | 15 +++-- .../documents/table_actions_component.rb | 7 --- .../answers/table_actions_component.html.erb | 2 +- .../answers/table_actions_component.rb | 7 --- .../videos/table_actions_component.html.erb | 2 +- .../answers/videos/table_actions_component.rb | 7 --- .../table_actions_component.html.erb | 4 +- .../poll/questions/table_actions_component.rb | 7 --- .../allowed_table_actions_component_spec.rb | 57 +++++++++++++++++++ 11 files changed, 91 insertions(+), 40 deletions(-) create mode 100644 app/components/admin/allowed_table_actions_component.html.erb create mode 100644 app/components/admin/allowed_table_actions_component.rb create mode 100644 spec/components/admin/allowed_table_actions_component_spec.rb diff --git a/app/components/admin/allowed_table_actions_component.html.erb b/app/components/admin/allowed_table_actions_component.html.erb new file mode 100644 index 000000000..df89fe8f7 --- /dev/null +++ b/app/components/admin/allowed_table_actions_component.html.erb @@ -0,0 +1,3 @@ +<%= render table_actions_component do %> + <%= content %> +<% end %> diff --git a/app/components/admin/allowed_table_actions_component.rb b/app/components/admin/allowed_table_actions_component.rb new file mode 100644 index 000000000..dc5f2e1d5 --- /dev/null +++ b/app/components/admin/allowed_table_actions_component.rb @@ -0,0 +1,20 @@ +class Admin::AllowedTableActionsComponent < ApplicationComponent + attr_reader :record, :options + delegate :can?, to: :helpers + delegate :action, to: :table_actions_component + + def initialize(record, **options) + @record = record + @options = options + end + + private + + def actions + (options[:actions] || [:edit, :destroy]).select { |action| can?(action, record) } + end + + def table_actions_component + @table_actions_component ||= Admin::TableActionsComponent.new(record, **options.merge(actions: actions)) + end +end diff --git a/app/components/admin/poll/questions/answers/documents/table_actions_component.html.erb b/app/components/admin/poll/questions/answers/documents/table_actions_component.html.erb index f2406512e..19e8e3ac2 100644 --- a/app/components/admin/poll/questions/answers/documents/table_actions_component.html.erb +++ b/app/components/admin/poll/questions/answers/documents/table_actions_component.html.erb @@ -1,9 +1,8 @@ -<%= render Admin::TableActionsComponent.new(document, - actions: actions, - destroy_path: document_path(document)) do |table_actions| %> - <%= table_actions.action(:download, - text: t("documents.buttons.download_document"), - path: document.attachment, - target: "_blank", - rel: "nofollow") %> +<%= render Admin::AllowedTableActionsComponent.new(document, + destroy_path: document_path(document)) do |actions| %> + <%= actions.action(:download, + text: t("documents.buttons.download_document"), + path: document.attachment, + target: "_blank", + rel: "nofollow") %> <% end %> diff --git a/app/components/admin/poll/questions/answers/documents/table_actions_component.rb b/app/components/admin/poll/questions/answers/documents/table_actions_component.rb index 38b7a7c08..da895ef1a 100644 --- a/app/components/admin/poll/questions/answers/documents/table_actions_component.rb +++ b/app/components/admin/poll/questions/answers/documents/table_actions_component.rb @@ -1,14 +1,7 @@ class Admin::Poll::Questions::Answers::Documents::TableActionsComponent < ApplicationComponent attr_reader :document - delegate :can?, to: :helpers def initialize(document) @document = document end - - private - - def actions - [:destroy].select { |action| can?(action, document) } - end end diff --git a/app/components/admin/poll/questions/answers/table_actions_component.html.erb b/app/components/admin/poll/questions/answers/table_actions_component.html.erb index a9fc5cd8a..d401f1a36 100644 --- a/app/components/admin/poll/questions/answers/table_actions_component.html.erb +++ b/app/components/admin/poll/questions/answers/table_actions_component.html.erb @@ -1 +1 @@ -<%= render Admin::TableActionsComponent.new(answer, actions: actions) %> +<%= render Admin::AllowedTableActionsComponent.new(answer) %> diff --git a/app/components/admin/poll/questions/answers/table_actions_component.rb b/app/components/admin/poll/questions/answers/table_actions_component.rb index 577e099b1..94b60b92e 100644 --- a/app/components/admin/poll/questions/answers/table_actions_component.rb +++ b/app/components/admin/poll/questions/answers/table_actions_component.rb @@ -1,14 +1,7 @@ class Admin::Poll::Questions::Answers::TableActionsComponent < ApplicationComponent attr_reader :answer - delegate :can?, to: :helpers def initialize(answer) @answer = answer end - - private - - def actions - [:edit, :destroy].select { |action| can?(action, answer) } - end end diff --git a/app/components/admin/poll/questions/answers/videos/table_actions_component.html.erb b/app/components/admin/poll/questions/answers/videos/table_actions_component.html.erb index f799eae21..e4ebef5f4 100644 --- a/app/components/admin/poll/questions/answers/videos/table_actions_component.html.erb +++ b/app/components/admin/poll/questions/answers/videos/table_actions_component.html.erb @@ -1 +1 @@ -<%= render Admin::TableActionsComponent.new(video, actions: actions) %> +<%= render Admin::AllowedTableActionsComponent.new(video) %> diff --git a/app/components/admin/poll/questions/answers/videos/table_actions_component.rb b/app/components/admin/poll/questions/answers/videos/table_actions_component.rb index 935cd5c80..06e772b6b 100644 --- a/app/components/admin/poll/questions/answers/videos/table_actions_component.rb +++ b/app/components/admin/poll/questions/answers/videos/table_actions_component.rb @@ -1,14 +1,7 @@ class Admin::Poll::Questions::Answers::Videos::TableActionsComponent < ApplicationComponent attr_reader :video - delegate :can?, to: :helpers def initialize(video) @video = video end - - private - - def actions - [:edit, :destroy].select { |action| can?(action, video) } - end end diff --git a/app/components/admin/poll/questions/table_actions_component.html.erb b/app/components/admin/poll/questions/table_actions_component.html.erb index 5858ad82c..736eda7af 100644 --- a/app/components/admin/poll/questions/table_actions_component.html.erb +++ b/app/components/admin/poll/questions/table_actions_component.html.erb @@ -1,3 +1,3 @@ -<%= render Admin::TableActionsComponent.new(question, actions: actions) do |table_actions| %> - <%= table_actions.action(:answers, text: t("admin.polls.show.edit_answers")) %> +<%= render Admin::AllowedTableActionsComponent.new(question) do |actions| %> + <%= actions.action(:answers, text: t("admin.polls.show.edit_answers")) %> <% end %> diff --git a/app/components/admin/poll/questions/table_actions_component.rb b/app/components/admin/poll/questions/table_actions_component.rb index 85c7bb279..ba4eb66f4 100644 --- a/app/components/admin/poll/questions/table_actions_component.rb +++ b/app/components/admin/poll/questions/table_actions_component.rb @@ -1,14 +1,7 @@ class Admin::Poll::Questions::TableActionsComponent < ApplicationComponent attr_reader :question - delegate :can?, to: :helpers def initialize(question) @question = question end - - private - - def actions - [:edit, :destroy].select { |action| can?(action, question) } - end end diff --git a/spec/components/admin/allowed_table_actions_component_spec.rb b/spec/components/admin/allowed_table_actions_component_spec.rb new file mode 100644 index 000000000..6396be6b8 --- /dev/null +++ b/spec/components/admin/allowed_table_actions_component_spec.rb @@ -0,0 +1,57 @@ +require "rails_helper" + +describe Admin::AllowedTableActionsComponent, controller: Admin::BaseController do + before do + sign_in(create(:administrator).user) + allow_any_instance_of(Admin::AllowedTableActionsComponent).to receive(:can?).and_return true + end + let(:record) { create(:banner, title: "Important!") } + + it "renders edit and destroy actions by default if they're allowed" do + component = Admin::AllowedTableActionsComponent.new(record) + + render_inline component + + expect(page).to have_link count: 1 + expect(page).to have_link "Edit" + expect(page).to have_button count: 1 + expect(page).to have_button "Delete" + end + + it "accepts an actions parameter" do + render_inline Admin::AllowedTableActionsComponent.new(record, actions: [:edit]) + + expect(page).to have_link "Edit" + expect(page).not_to have_button "Delete" + end + + it "accepts custom options" do + render_inline Admin::AllowedTableActionsComponent.new(record, edit_text: "change", edit_path: "/myedit") + + expect(page).to have_link "change", href: "/myedit" + end + + it "accepts custom content" do + render_inline Admin::AllowedTableActionsComponent.new(record) do + "Main".html_safe + end + + expect(page).to have_link count: 2 + expect(page).to have_link "Main", href: "/" + expect(page).to have_link "Edit" + + expect(page).to have_button count: 1 + expect(page).to have_button "Delete" + end + + it "only renders the allowed actions" do + component = Admin::AllowedTableActionsComponent.new(record) + allow(component).to receive(:can?).with(:edit, record).and_return true + allow(component).to receive(:can?).with(:destroy, record).and_return false + + render_inline component + + expect(page).to have_link "Edit" + expect(page).not_to have_button "Delete" + end +end