Pour mon premier article sur ce blog, je vais être assez technique, alors d’avance désolé pour les non-techniciens qui nous lisent ;)
Nous allons parler ici d’ActiveScaffold, un plugin pour Ruby on Rails qui permet d’obtenir rapidement et simplement des interfaces CRUD sur vos Models… En fait nous allons surtout parler de sa personnalisation !
Pré-requis :
Le but :
Afficher ou non des action_link en fonction de la valeur d’une colonne de la base de données pour chacun des rang scaffoldés. mais si mais si vous suivez !
La base
Dans notre projet Rails, il y un model User, auquel correspond donc une table user en base de donnée.
Ce projet possède une interface d’administration qui fonctionne avec ActiveScaffold, il y a donc un 2ème controller pour notre user, le UserController de la partie administration.
Dans notre projet nous voulons créer un action_link supplémentaire pour changer la valeur d’une colonne de notre objet User en base. On ajoute donc à notre UsersController de zone d’administration :
config.action_links.add “validate”, :type => :record
On va donc logiquement définir dans notre controller une méthode validate qui va effectuer le traitement voulu. Jusque là rien de bien compliqué, c’est la base d’ActiveScaffold.
Ça se complique…
A présent, nous voudrions que ce lien n’apparaissent que lorsqu’une colonne du user en base concernée possède une certaine valeur.
Pour ce faire, il faut rajouter un argument magique, j’ai nommé : security_method.
Dans le principe cet argument permet d’appeler une méthode du controller concerné pour tester des condition sur la colonne scaffoldée elle-même.
On obtient donc :
config.action_links.add “validate”, :type => :record , :security_method => :need_validation?
Ainsi avant d’afficher le lien validate, la méthode need_validation? serait appelée…
Le problème
Ici il faut déterminer si oui ou non on va afficher notre action_link, ce qu’on va tester ce n’est donc pas un état de la colonne scaffoldée, mais chacun des records que l’on parcours dans notre scaffold !
… Mais il y a une petite astuce ;)
La solution va être de créer une vue qui surchargera automatiquement l’affichage actuel du scaffold, et dans lequel on va pouvoir accéder aux champs parcourus.
ATTENTION : Cette technique demande à ce que la méthode appelée par security_method soit dans le model et non plus dans le controller !
Il faut créer une vue nommée _list_actions.html.erb et la placer dans le répertoire des vues admin du controller concerné. Ici views/admin/users/_list_actions.html.erb
Dans cette vue nous allons pouvoir accéder à chaque record concerné ainsi qu’à leurs action_link :
Regardez bien la ligne 7, c’est la seule que nous avons changé par rapport au fichier _list_actions.html.erb standard d’ActiveScaffold.
<table cellpadding=”0” cellspacing=”0”>
<tr>
<td class=”indicator-container”>
<%= loading_indicator_tag(:action => :record, :id => record.id) %>
</td>
<% active_scaffold_config.action_links.each :record do |link| -%>
<% next if (controller.respond_to?(link.security_method) and !controller.send(link.security_method)) || (record.respond_to?(link.security_method) and !record.send(link.security_method)) -%>
<td>
<%= record.authorized_for?(:action => link.crud_type) ? render_action_link(link, url_options) : “<a class=’disabled’>#{link.label}</a>” -%>
</td>
<% end -%>
</tr>
</table>
Toute l’astuce réside dans la seconde partie du test ligne 7, qui va exécuter cette méthode dans le model en plus de la tester dans le controller. Du coup même si c’est un “hack” on ne change pas le fonctionnement d’Active Scaffold !
Conclusion
On peux ainsi simplifier grandement l’administration de notre site, puisque seul les rangs qui nécessites cette validation présentent le bouton !