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?

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


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)

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


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)

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

11

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

ApplicationController.helpers.my_helper_method
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.