Utilisation des helpers dans le modèle: comment inclure des dépendances d'assistance?

100

J'écris un modèle qui gère l'entrée utilisateur à partir d'une zone de texte. Suivant les conseils de http://blog.caboo.se/articles/2008/8/25/sanitize-your-users-html-input , je nettoie l'entrée dans le modèle avant de l'enregistrer dans la base de données, en utilisant le before_validate rappeler.

Les parties pertinentes de mon modèle ressemblent à ceci:

include ActionView::Helpers::SanitizeHelper

class Post < ActiveRecord::Base {
  before_validation :clean_input

  ...

  protected

  def clean_input
    self.input = sanitize(self.input, :tags => %w(b i u))
  end
end

Inutile de dire que cela ne fonctionne pas. J'obtiens l'erreur suivante lorsque j'essaie d'enregistrer une nouvelle publication.

undefined method `white_list_sanitizer' for #<Class:0xdeadbeef>

Apparemment, SanitizeHelper crée une instance de HTML :: WhiteListSanitizer, mais quand je le mélange dans mon modèle, il ne trouve pas HTML :: WhiteListSanitizer. Pourquoi? Que puis-je faire pour résoudre ce problème?

O. Frabjous-Dey
la source

Réponses:

133

Modifiez simplement la première ligne comme suit:

include ActionView::Helpers

cela le fera fonctionner.

MISE À JOUR: Pour Rails 3, utilisez:

ActionController::Base.helpers.sanitize(str)

Le mérite revient à la réponse de Lornc

Alfreddd
la source
Je
1
Merci. Je l'ai fait fonctionner en déplaçant l'inclusion à l'intérieur de la définition de classe.
O. Frabjous-Dey le
1
Avec ça, je reçois stack level too deep. C'est dans une méthode before_save.
Automatico
42
Veuillez ne pas mélanger les problèmes de couche de vue avec les modèles d'enregistrement actifs. C'est une pratique terrible. Une bien meilleure approche consiste à placer un objet de désinfection des données d'entrée autonome devant AR et à en extraire les attributs «propres».
solnic le
1
C'est une très mauvaise solution et doit être évitée comme le feu. Rails est basé sur le framework MVC (Model View Controller) où l'assistant vient dans la partie View, vous ne devez donc pas mélanger les méthodes d'assistance de vue avec le modèle.
jedi
132

Cela vous donne juste la méthode d'assistance sans les effets secondaires du chargement de chaque méthode ActionView :: Helpers dans votre modèle:

ActionController::Base.helpers.sanitize(str)
lornc
la source
6
Pour les gens lents comme moi - vous n'avez rien à inclure, utilisez simplement ActionController :: Base.helpers.sanitize ("Sur la chaîne que vous voulez nettoyer")
Edward
Merci, travaillé dans Rails 2.3.14 alors que la réponse acceptée ne l'a pas fait.
ChrisInEdmonton
J'ai ajouté une méthode à application_helper, mais je n'ai pas pu y accéder à partir du modèle en utilisant ActionController :: Base.helpers.my_method (options) en utilisant Rails 3.0.3?
Tom Rossi
35

Cela fonctionne mieux pour moi:

Facile:

ApplicationController.helpers.my_helper_method

Avance:

class HelperProxy < ActionView::Base
  include ApplicationController.master_helper_module

  def current_user
    #let helpers act like we're a guest
    nil
  end       

  def self.instance
    @instance ||= new
  end
end

Source: http://makandracards.com/makandra/1307-how-to-use-helper-methods-inside-a-model

skozz
la source
1
Le ApplicationController.master_helper_modulen'existe plus dans les rails 3 et 4 il apparaît. Le ApplicationController.helpersest un bon cependant.
Samuel
J'ai voté pour cela (l'option simple) car cela répondait à mes besoins - je n'ai besoin que d'un assistant qui utilise les informations enregistrées par un filtre avant dans ApplicationController, donc dans mon cas, rendre l'association explicite est un rappel qu'il y a un couplage. [Le cas d'utilisation est une application multi-domaine, qui émet des e-mails via un notificateur de modèle avec un lien URL vers l'application - cette URL change en fonction du domaine de la requête Web]
iheggie
24

Pour accéder aux helpers depuis vos propres contrôleurs, utilisez simplement:

OrdersController.helpers.order_number(@order)
Tarmo
la source
2
Juste en utilisant ApplicationController.helpers.order_number(@order). Cela signifie que la order_numberlocalisation était surOrder Helper
ksugiarto
3
@rowanu Il dit "pour accéder aux (helpers de vos propres contrôleurs)", pas "(pour accéder aux helpers) de vos propres contrôleurs".
Ajedi32
11

Je ne recommanderais aucune de ces méthodes. Au lieu de cela, placez-le dans son propre espace de noms.

class Post < ActiveRecord::Base
  def clean_input
    self.input = Helpers.sanitize(self.input, :tags => %w(b i u))
  end

  module Helpers
    extend ActionView::Helpers::SanitizeHelper
  end
end
axsuul
la source
11

Si vous souhaitez utiliser my_helper_methodun modèle à l' intérieur d'un modèle, vous pouvez écrire:

ApplicationController.helpers.my_helper_method
Atchyut Nagabhairava
la source