diff options
| author | Teddy Wing | 2017-06-14 11:14:16 +0200 |
|---|---|---|
| committer | Teddy Wing | 2017-06-14 11:40:54 +0200 |
| commit | 734de24950c6ae490d4781799c8a6d805944e6aa (patch) | |
| tree | be5fc5d25253c04b189d97046220e7bee9052972 | |
| parent | 1c70b12b7c71a428bfafc601d5538392ad2113bb (diff) | |
| download | chouette-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.rb | 7 | ||||
| -rw-r--r-- | app/decorators/referential_decorator.rb | 17 | ||||
| -rw-r--r-- | app/helpers/table_builder_helper.rb | 109 | ||||
| -rw-r--r-- | app/views/workbenches/_filters.html.slim | 4 |
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 |
