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`.
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
<%= render table_actions_component do %>
|
||||||
|
<%= content %>
|
||||||
|
<% end %>
|
||||||
20
app/components/admin/allowed_table_actions_component.rb
Normal file
20
app/components/admin/allowed_table_actions_component.rb
Normal file
@@ -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
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
<%= render Admin::TableActionsComponent.new(document,
|
<%= render Admin::AllowedTableActionsComponent.new(document,
|
||||||
actions: actions,
|
destroy_path: document_path(document)) do |actions| %>
|
||||||
destroy_path: document_path(document)) do |table_actions| %>
|
<%= actions.action(:download,
|
||||||
<%= table_actions.action(:download,
|
text: t("documents.buttons.download_document"),
|
||||||
text: t("documents.buttons.download_document"),
|
path: document.attachment,
|
||||||
path: document.attachment,
|
target: "_blank",
|
||||||
target: "_blank",
|
rel: "nofollow") %>
|
||||||
rel: "nofollow") %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,14 +1,7 @@
|
|||||||
class Admin::Poll::Questions::Answers::Documents::TableActionsComponent < ApplicationComponent
|
class Admin::Poll::Questions::Answers::Documents::TableActionsComponent < ApplicationComponent
|
||||||
attr_reader :document
|
attr_reader :document
|
||||||
delegate :can?, to: :helpers
|
|
||||||
|
|
||||||
def initialize(document)
|
def initialize(document)
|
||||||
@document = document
|
@document = document
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def actions
|
|
||||||
[:destroy].select { |action| can?(action, document) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<%= render Admin::TableActionsComponent.new(answer, actions: actions) %>
|
<%= render Admin::AllowedTableActionsComponent.new(answer) %>
|
||||||
|
|||||||
@@ -1,14 +1,7 @@
|
|||||||
class Admin::Poll::Questions::Answers::TableActionsComponent < ApplicationComponent
|
class Admin::Poll::Questions::Answers::TableActionsComponent < ApplicationComponent
|
||||||
attr_reader :answer
|
attr_reader :answer
|
||||||
delegate :can?, to: :helpers
|
|
||||||
|
|
||||||
def initialize(answer)
|
def initialize(answer)
|
||||||
@answer = answer
|
@answer = answer
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def actions
|
|
||||||
[:edit, :destroy].select { |action| can?(action, answer) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<%= render Admin::TableActionsComponent.new(video, actions: actions) %>
|
<%= render Admin::AllowedTableActionsComponent.new(video) %>
|
||||||
|
|||||||
@@ -1,14 +1,7 @@
|
|||||||
class Admin::Poll::Questions::Answers::Videos::TableActionsComponent < ApplicationComponent
|
class Admin::Poll::Questions::Answers::Videos::TableActionsComponent < ApplicationComponent
|
||||||
attr_reader :video
|
attr_reader :video
|
||||||
delegate :can?, to: :helpers
|
|
||||||
|
|
||||||
def initialize(video)
|
def initialize(video)
|
||||||
@video = video
|
@video = video
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def actions
|
|
||||||
[:edit, :destroy].select { |action| can?(action, video) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<%= render Admin::TableActionsComponent.new(question, actions: actions) do |table_actions| %>
|
<%= render Admin::AllowedTableActionsComponent.new(question) do |actions| %>
|
||||||
<%= table_actions.action(:answers, text: t("admin.polls.show.edit_answers")) %>
|
<%= actions.action(:answers, text: t("admin.polls.show.edit_answers")) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,14 +1,7 @@
|
|||||||
class Admin::Poll::Questions::TableActionsComponent < ApplicationComponent
|
class Admin::Poll::Questions::TableActionsComponent < ApplicationComponent
|
||||||
attr_reader :question
|
attr_reader :question
|
||||||
delegate :can?, to: :helpers
|
|
||||||
|
|
||||||
def initialize(question)
|
def initialize(question)
|
||||||
@question = question
|
@question = question
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def actions
|
|
||||||
[:edit, :destroy].select { |action| can?(action, question) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -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
|
||||||
|
"<a href='/'>Main</a>".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
|
||||||
Reference in New Issue
Block a user