Usando auxiliares no modelo: como incluir dependências de auxiliares?

100

Estou escrevendo um modelo que lida com a entrada do usuário de uma área de texto. Seguindo o conselho de http://blog.caboo.se/articles/2008/8/25/sanitize-your-users-html-input , estou limpando a entrada no modelo antes de salvar no banco de dados, usando o before_validate ligue de volta.

As partes relevantes do meu modelo são assim:

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

Desnecessário dizer que isso não funciona. Recebo o seguinte erro quando tento salvar uma nova postagem.

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

Aparentemente, SanitizeHelper cria uma instância de HTML :: WhiteListSanitizer, mas quando eu misturo em meu modelo, ele não consegue encontrar HTML :: WhiteListSanitizer. Por quê? O que posso fazer para corrigir isso?

O. Frabjous-Dey
fonte

Respostas:

133

Basta alterar a primeira linha da seguinte forma:

include ActionView::Helpers

isso fará com que funcione.

ATUALIZAÇÃO: Para Rails 3, use:

ActionController::Base.helpers.sanitize(str)

O crédito vai para a resposta de lornc

Alfreddd
fonte
não poderia ter dito melhor
Tilendor
1
Obrigado. Comecei a trabalhar movendo a inclusão para dentro da definição de classe.
O. Frabjous-Dey
1
Com isso eu entendo stack level too deep. É um método before_save.
Automatico
42
Por favor, não misture preocupações de camada de visão com modelos de registro ativo. Essa é uma prática terrível. Uma abordagem muito melhor é colocar um objeto sanitizador de dados de entrada autônomo na frente do AR e recuperar atributos "limpos" dele.
solnic
1
Esta é uma solução muito ruim e deve ser evitada como o fogo. Rails é baseado no framework MVC (Model View Controller) onde o helper vem na parte View, então você não deve misturar métodos view helper com model.
jedi
132

Isso fornece apenas o método auxiliar sem os efeitos colaterais de carregar cada método ActionView :: Helpers em seu modelo:

ActionController::Base.helpers.sanitize(str)
lornc
fonte
6
Para pessoas lentas como eu - você não precisa incluir nada, apenas use ActionController :: Base.helpers.sanitize ("Na string que você deseja higienizar")
Edward
Obrigado, funcionou no Rails 2.3.14 enquanto a resposta aceita não.
ChrisInEdmonton
Eu adicionei um método ao application_helper, mas não consegui acessá-lo do modelo usando ActionController :: Base.helpers.my_method (options) usando Rails 3.0.3?
Tom Rossi,
35

Isso funciona melhor para mim:

Simples:

ApplicationController.helpers.my_helper_method

Avançar:

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

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

Skozz
fonte
1
O ApplicationController.master_helper_modulenão existe mais no Rails 3 e 4 ao que parece. O ApplicationController.helpersé um bom, porém.
Samuel
Votei nesta opção (a opção simples) porque atende às minhas necessidades - eu só preciso de um helper que está usando informações salvas por um filtro before no ApplicationController, então, no meu caso, tornar a associação explícita é um lembrete de que há um acoplamento. [O caso de uso é um aplicativo de vários domínios, que emite e-mails por meio de um notificador de modelo com um link de url de volta para o aplicativo - esse url muda dependendo do domínio da solicitação da web]
iheggie
24

Para acessar auxiliares de seus próprios controladores, basta usar:

OrdersController.helpers.order_number(@order)
Tarmo
fonte
2
Apenas usando ApplicationController.helpers.order_number(@order). Isso significa que order_numberfoi localizado emOrder Helper
ksugiarto
3
@rowanu Ele está dizendo "para acessar (ajudantes de seus próprios controladores)", não "(para acessar ajudantes) de seus próprios controladores".
Ajedi32
11

Eu não recomendaria nenhum desses métodos. Em vez disso, coloque-o em seu próprio namespace.

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
fonte
11

Se você quiser usar o my_helper_methodinterior de um modelo, pode escrever:

ApplicationController.helpers.my_helper_method
Atchyut Nagabhairava
fonte