Decorateurs
Usage
On ne définit qu'un seul décorateur, qui hérite de la classe AF83::Decorator.
Il est responsable de décorer les collections ainsi que les instances.
Dans les controlleurs, le code devient donc simplement:
# dans l'index
@items = ItemDecorator.decorator(@items)
# dans le show
@item = @item.decorate
Les actions disponibles sur la collection sont définies à la racine du décorateur,
alors que celles attachées aux instances sont définies à l'aide du block with_instance_decorator.
Pour définir une action, on utilise la méthode action_link. Les options disponibles sont:
-
on: limite la visibilité du lien aux actions listées (on: %i(show index)) -
if: reçoit uneProc, et n'affiche le lien que si le résultat est trueish -
policy: le lien n'est accessible que si l'utilisateur courant dispose du droit correspondant sur l'objet décoré (on ne passe que le nom de la permission :edit,create, etc.) -
feature: comme pourpolicy, mais avec unefeature -
weight: pour modifier l'ordre d'affichage des liens (par défaut l'ordre de déclaration est utilisé)
Les actions sont aussi réparties dans des groupes. Il y a plusieurs syntaxes possibles pour cela:
groups: { primary: true, secondary: %i(index show), any_other_group: :index)}
Des raccourcis sont disponibles pour les groupes primary, secondary et footer.
On peut dont écrire action_link primary: :index plutôt que action_link groups: {primary: :index}
Le contenu du lien est défini à l'aide d'un bloc (cf exemple). Chaque méthode appelée sur l'objet passé au bloc est convertie en attribut sur la balise HTML résultante, à l'exception de certaines méthodes spécifiques:
-
extra_class: ajoute une (ou des) classe(s) au lien. Peut recevoir un tableau ou une string. -
class: REMPLACE les classes du lien. Peut recevoir un tableau ou une string. -
type: permet de définir le type de balise HTML à utiliser. Seule la valeurbuttonest implémentée, les autres fallback sur un<a>
Raccourcis
4 méthodes sont disponibles pour définir des actions communes:
-
create_action_link: pour ajouter un lien de création d'un objet sur une collection -
show_action_link: pour ajouter un lien d'affichage d'un objet sur une instance -
edit_action_link: pour ajouter un lien de modification d'un objet sur une instance -
destroy_action_link: pour ajouter un lien de suppression d'un objet sur une instance
Ils sont définis dans la classe AF83::EnhancedDecorator.
Comportement
Le comportement par défaut est le suivant:
Sur la page index
Dans la zone principale du header (qui est reprise dans le header sticky), on affiche les actions
du groupe primary de la collection.
Dans la zone secondaire du header (sous la one principale), on affiche les actions
du groupe secondary de la collection.
Dans le TableBuilderHelper, on affiche toutes les actions des groupes primary, secondary et footer sur chaque instance,
groupées par groupe. A noter, le groupe footer est systématiquement affiché en dernier.
Sur la page show
Dans la zone principale du header (qui est reprise dans le header sticky), on affiche les actions
du groupe primary de l'objet.
Dans la zone secondaire du header (sous la one principale), on affiche les actions
du groupe secondary de l'objet.
Exemples
Decorateur simple
class CalendarDecorator < AF83::Decorator
decorates Calendar
create_action_link
with_instance_decorator do |instance_decorator|
instance_decorator.show_action_link
instance_decorator.edit_action_link
instance_decorator.destroy_action_link do |l|
l.data {{ confirm: h.t('calendars.actions.destroy_confirm') }}
end
end
end
Decorateur plus complexe
class LineDecorator < AF83::Decorator
decorates Chouette::Line
create_action_link do |l|
l.content t('lines.actions.new')
l.href { h.new_line_referential_line_path(context[:line_referential]) }
end
with_instance_decorator do |instance_decorator|
instance_decorator.show_action_link do |l|
l.content t('lines.actions.show')
l.href { [context[:line_referential], object] }
end
instance_decorator.action_link do |l|
l.content t('lines.actions.show_network')
l.href { [context[:line_referential], object.network] }
end
instance_decorator.action_link do |l|
l.content t('lines.actions.show_company')
l.href { [context[:line_referential], object.company] }
l.disabled { object.company.nil? }
end
can_edit_line = ->(){ h.policy(Chouette::Line).create? && context[:line_referential].organisations.include?(context[:current_organisation]) }
instance_decorator.with_condition can_edit_line do
edit_action_link do |l|
l.content {|l| l.primary? ? h.t('actions.edit') : h.t('lines.actions.edit') }
l.href { h.edit_line_referential_line_path(context[:line_referential], object.id) }
end
action_link on: :index, secondary: :index do |l|
l.content t('lines.actions.new')
l.href { h.new_line_referential_line_path(context[:line_referential]) }
end
end
instance_decorator.action_link policy: :deactivate, secondary: :show, footer: :index do |l|
l.content { h.deactivate_link_content('lines.actions.deactivate') }
l.href { h.deactivate_line_referential_line_path(context[:line_referential], object) }
l.method :put
l.data confirm: h.t('lines.actions.deactivate_confirm')
l.extra_class "delete-action"
end
instance_decorator.action_link policy: :activate, secondary: :show, footer: :index do |l|
l.content { h.activate_link_content('lines.actions.activate') }
l.href { h.activate_line_referential_line_path(context[:line_referential], object) }
l.method :put
l.data confirm: h.t('lines.actions.activate_confirm')
l.extra_class "delete-action"
end
instance_decorator.destroy_action_link do |l|
l.content { h.destroy_link_content('lines.actions.destroy') }
l.href { h.line_referential_line_path(context[:line_referential], object) }
l.data confirm: h.t('lines.actions.destroy_confirm')
l.extra_class "delete-action"
end
end
end
Breadcrumb
Le fil d'ariane est géré via le gem Gretel. La configuration se fait via le fichier config/breadcrumbs.rb.