aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeddy Wing2017-06-14 11:14:16 +0200
committerTeddy Wing2017-06-14 11:40:54 +0200
commit734de24950c6ae490d4781799c8a6d805944e6aa (patch)
treebe5fc5d25253c04b189d97046220e7bee9052972
parent1c70b12b7c71a428bfafc601d5538392ad2113bb (diff)
downloadchouette-core-734de24950c6ae490d4781799c8a6d805944e6aa.tar.bz2
Workbenches#show: Use common referential action_links in table gear menu
Get our `ReferentialDecorator` working for a collection of `Referential`s. We decorate the `ActiveRecord::Relation` of referentials that gets passed to the table builder. This enables us to call the `#action_links` method on those referentials, getting a list of links that should appear in the gear menu. From that list, we can generate the proper HTML to stick into the menu. This was my first test of reusing the `#action_links` for both the header buttons in Referentials#show and the list in Workbenches#show. Ran into some trouble. The issue was that decorating the collection with Draper's defaults doesn't delegate methods on the collection object (in other words, `ActiveRecord::Relation`). We call methods on the collection in our code, and doing so on our new decorated collection caused errors. As a first step to get around the first batch of errors, I changed the `_filters.html.slim` template to call `#human_attribute_name` on `Referential` model directly, instead of on the Relation. There was some additional weirdness that Luc tipped me off to as we have a `Chouette::ActiveRecord` class that defines its own `#human_attribute_name` method. Switching the callee to the model fixed this error. Subsequently, I ran into a problem in the `TableBuilderHelper`. In that code, we call `collection.model` to determine the class of objects in our table. Now that I think about it, maybe we should just pass this information when calling `table_builder`. Let's do that because it would be better. Anyway, to enable that `ActiveRecord::Relation#model` method to be called, I created a Draper `CollectionDecorator` that delegates the `#model` method. This allows us to call `#model` on the decorated collection of referentials (or other objects). Finally, I ran into another delegate problem for our pagination method calls. Fortunately, Draper provides some code for a `CollectionDecorator` for pagination. I copied this and used it in conjunction with my custom `ModelDecorator` to properly delegate all necessary collection methods for a collection of Referentials. Stuck my `PaginatingDecorator` and `ModelDecorator` right in the `referential_decorator.rb` file for now just for testing until I got things working. Needed to import this file in the controller where we decorate the collection. Not entirely sure why but my guess is that it's because the loader connects classes to file names and we have several different classes in that file. Maybe I'm totally wrong on that. Anyway, will be moving those classes to separate files later. In the controller, decorate our `Referential` collection with the `ModelDecorator` (which inherits from `PaginatingDecorator`, giving us those delegated methods), and ensure the objects inside the collection get decorated with our original `ReferentialDecorator`. In `TableBuilderHelper#build_links`, comment out all the existing link building code and instead map over the `#action_links` provided by the decorator. Currently this should only work for `Referential` collections, but the idea is to use that pattern for all table objects. NOTE: We should add a doc comment to the table builder that tells people that they need a decorator for their model in order for it to work. Refs #3479
-rw-r--r--app/controllers/workbenches_controller.rb7
-rw-r--r--app/decorators/referential_decorator.rb17
-rw-r--r--app/helpers/table_builder_helper.rb109
-rw-r--r--app/views/workbenches/_filters.html.slim4
4 files changed, 85 insertions, 52 deletions
diff --git a/app/controllers/workbenches_controller.rb b/app/controllers/workbenches_controller.rb
index ccd55965b..56f9136b3 100644
--- a/app/controllers/workbenches_controller.rb
+++ b/app/controllers/workbenches_controller.rb
@@ -1,3 +1,6 @@
+# TODO: Try not importing
+require 'referential_decorator'
+
class WorkbenchesController < BreadcrumbController
before_action :query_params, only: [:show]
@@ -14,6 +17,10 @@ class WorkbenchesController < BreadcrumbController
q_for_result =
scope.ransack(params[:q].merge(archived_at_not_null: nil, archived_at_null: nil))
@wbench_refs = sort_result(q_for_result.result).paginate(page: params[:page], per_page: 30)
+ @wbench_refs = ModelDecorator.decorate(
+ @wbench_refs,
+ with: ReferentialDecorator
+ )
@q = scope.ransack(params[:q])
show! do
diff --git a/app/decorators/referential_decorator.rb b/app/decorators/referential_decorator.rb
index 1c2347529..45a4b38d1 100644
--- a/app/decorators/referential_decorator.rb
+++ b/app/decorators/referential_decorator.rb
@@ -1,3 +1,20 @@
+# Delegates 'will_paginate' methods
+class PaginatingDecorator < Draper::CollectionDecorator
+ delegate(
+ :current_page,
+ :per_page,
+ :offset,
+ :total_entries,
+ :total_pages
+ )
+end
+
+
+class ModelDecorator < PaginatingDecorator
+ delegate :model
+end
+
+
class ReferentialDecorator < Draper::Decorator
delegate_all
diff --git a/app/helpers/table_builder_helper.rb b/app/helpers/table_builder_helper.rb
index 6f9073662..47401a807 100644
--- a/app/helpers/table_builder_helper.rb
+++ b/app/helpers/table_builder_helper.rb
@@ -126,57 +126,66 @@ module TableBuilderHelper
end
menu = content_tag :ul, class: 'dropdown-menu' do
- actions.map do |action|
- polymorph_url = []
-
- unless [:show, :delete].include? action
- polymorph_url << action
- end
-
- polymorph_url += polymorphic_url_parts(item)
-
- if action == :delete
- if policy(item).present?
- if policy(item).destroy?
- # TODO: This tag is exactly the same as the one below it
- content_tag :li, '', class: 'delete-action' do
- link_to(polymorph_url, method: :delete, data: { confirm: 'Etes-vous sûr(e) de vouloir effectuer cette action ?' }) do
- txt = t("actions.#{action}")
- pic = content_tag :span, '', class: 'fa fa-trash'
- pic + txt
- end
- end
- end
- else
- content_tag :li, '', class: 'delete-action' do
- link_to(polymorph_url, method: :delete, data: { confirm: 'Etes-vous sûr(e) de vouloir effectuer cette action ?' }) do
- txt = t("actions.#{action}")
- pic = content_tag :span, '', class: 'fa fa-trash'
- pic + txt
- end
- end
- end
-
- elsif action == :edit
- if policy(item).present?
- if policy(item).update?
- content_tag :li, link_to(t("actions.#{action}"), polymorph_url)
- end
- else
- content_tag :li, link_to(t("actions.#{action}"), polymorph_url)
- end
- elsif action == :archive
- unless item.archived?
- content_tag :li, link_to(t("actions.#{action}"), polymorph_url, method: :put)
- end
- elsif action == :unarchive
- if item.archived?
- content_tag :li, link_to(t("actions.#{action}"), polymorph_url, method: :put)
- end
- else
- content_tag :li, link_to(t("actions.#{action}"), polymorph_url)
- end
+ item.action_links.map do |link|
+ content_tag :li, link_to(
+ link.name,
+ link.href,
+ method: link.method,
+ data: link.data
+ )
end.join.html_safe
+
+ # actions.map do |action|
+ # polymorph_url = []
+ #
+ # unless [:show, :delete].include? action
+ # polymorph_url << action
+ # end
+ #
+ # polymorph_url += polymorphic_url_parts(item)
+ #
+ # if action == :delete
+ # if policy(item).present?
+ # if policy(item).destroy?
+ # # TODO: This tag is exactly the same as the one below it
+ # content_tag :li, '', class: 'delete-action' do
+ # link_to(polymorph_url, method: :delete, data: { confirm: 'Etes-vous sûr(e) de vouloir effectuer cette action ?' }) do
+ # txt = t("actions.#{action}")
+ # pic = content_tag :span, '', class: 'fa fa-trash'
+ # pic + txt
+ # end
+ # end
+ # end
+ # else
+ # content_tag :li, '', class: 'delete-action' do
+ # link_to(polymorph_url, method: :delete, data: { confirm: 'Etes-vous sûr(e) de vouloir effectuer cette action ?' }) do
+ # txt = t("actions.#{action}")
+ # pic = content_tag :span, '', class: 'fa fa-trash'
+ # pic + txt
+ # end
+ # end
+ # end
+ #
+ # elsif action == :edit
+ # if policy(item).present?
+ # if policy(item).update?
+ # content_tag :li, link_to(t("actions.#{action}"), polymorph_url)
+ # end
+ # else
+ # content_tag :li, link_to(t("actions.#{action}"), polymorph_url)
+ # end
+ # elsif action == :archive
+ # unless item.archived?
+ # content_tag :li, link_to(t("actions.#{action}"), polymorph_url, method: :put)
+ # end
+ # elsif action == :unarchive
+ # if item.archived?
+ # content_tag :li, link_to(t("actions.#{action}"), polymorph_url, method: :put)
+ # end
+ # else
+ # content_tag :li, link_to(t("actions.#{action}"), polymorph_url)
+ # end
+ # end.join.html_safe
end
content_tag :div, trigger + menu, class: 'btn-group'
diff --git a/app/views/workbenches/_filters.html.slim b/app/views/workbenches/_filters.html.slim
index 7c5055963..0aedbdd62 100644
--- a/app/views/workbenches/_filters.html.slim
+++ b/app/views/workbenches/_filters.html.slim
@@ -12,7 +12,7 @@
= f.input :associated_lines_id_eq, as: :select, collection: @workbench.lines.includes(:company).order(:name), input_html: { 'data-select2ed': 'true', 'data-select2ed-placeholder': 'Indiquez une ligne...' }, label: false, label_method: :display_name, wrapper_html: { class: 'select2ed'}
.form-group.togglable
- = f.label @wbench_refs.human_attribute_name(:status), required: false, class: 'control-label'
+ = f.label Referential.human_attribute_name(:status), required: false, class: 'control-label'
.form-group.checkbox_list
= f.input :archived_at_not_null, label: ("<span>Conservé<span class='fa fa-archive'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' }
= f.input :archived_at_null, label: ("<span>En préparation<span class='sb sb-lg sb-preparing'></span></span>").html_safe, as: :boolean, wrapper_html: { class: 'checkbox-wrapper' }
@@ -22,7 +22,7 @@
= f.input :organisation_name_eq_any, collection: Organisation.order('name').pluck(:name), as: :check_boxes, label: false, label_method: lambda{|w| ("<span>#{w}</span>").html_safe}, required: false, wrapper_html: { class: 'checkbox_list' }
.form-group.togglable
- = f.label @wbench_refs.human_attribute_name(:validity_period), required: false, class: 'control-label'
+ = f.label Referential.human_attribute_name(:validity_period), required: false, class: 'control-label'
.filter_menu
= f.simple_fields_for :validity_period do |p|
= p.input :begin_gteq, as: :date, label: t('simple_form.from'), wrapper_html: { class: 'date filter_menu-item' }, default: @begin_range, include_blank: @begin_range ? false : true