Verwenden von Helfern im Modell: Wie füge ich Hilfsabhängigkeiten hinzu?


100

Ich schreibe ein Modell, das Benutzereingaben aus einem Textbereich verarbeitet. Nach den Ratschlägen von http://blog.caboo.se/articles/2008/8/25/sanitize-your-users-html-input bereinige ich die Eingabe im Modell, bevor ich sie mit dem before_validate in der Datenbank speichere zurückrufen.

Die relevanten Teile meines Modells sehen folgendermaßen aus:

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

Das funktioniert natürlich nicht. Ich erhalte die folgende Fehlermeldung, wenn ich versuche, einen neuen Beitrag zu speichern.

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

Anscheinend erstellt SanitizeHelper eine Instanz von HTML :: WhiteListSanitizer, aber wenn ich es in mein Modell mische, kann es HTML :: WhiteListSanitizer nicht finden. Warum? Was kann ich dagegen tun, um das Problem zu beheben?

Antworten:


133

Ändern Sie einfach die erste Zeile wie folgt:

include ActionView::Helpers

das wird es funktionieren lassen.

UPDATE: Für Rails 3 verwenden Sie:

ActionController::Base.helpers.sanitize(str)

Gutschrift geht an lorncs Antwort


Ich

1
Vielen Dank. Ich habe es zum Laufen gebracht, indem ich das Include in die Klassendefinition verschoben habe.
O. Frabjous-Dey

1
Damit verstehe ich stack level too deep. Es befindet sich in einer before_save-Methode.
Automatico

41
Bitte mischen Sie Bedenken hinsichtlich der Ansichtsebene nicht mit aktiven Datensatzmodellen. Das ist eine schreckliche Praxis. Ein viel besserer Ansatz besteht darin, ein eigenständiges Desinfektionsobjekt für Eingabedaten vor AR zu stellen und "saubere" Attribute daraus abzurufen.
Solnic

1
Dies ist eine sehr schlechte Lösung und sollte wie Feuer vermieden werden. Rails basiert auf dem MVC-Framework (Model View Controller), in dem der Helfer im View-Teil enthalten ist. Daher sollten Sie die View-Helfer-Methoden nicht mit dem Modell mischen.
Jedi

132

Auf diese Weise erhalten Sie nur die Hilfsmethode ohne die Nebenwirkungen des Ladens jeder ActionView :: Helpers-Methode in Ihr Modell:

ActionController::Base.helpers.sanitize(str)

6
Für die langsamen Leute wie mich - Sie müssen nichts einschließen, verwenden Sie einfach ActionController :: Base.helpers.sanitize ("Auf der Zeichenfolge, die Sie bereinigen möchten")
Edward

Vielen Dank, habe in Rails 2.3.14 gearbeitet, die akzeptierte Antwort jedoch nicht.
ChrisInEdmonton

Ich habe dem application_helper eine Methode hinzugefügt, konnte jedoch mit ActionController :: Base.helpers.my_method (Optionen) mit Rails 3.0.3 vom Modell aus nicht darauf zugreifen.
Tom Rossi

35

Das funktioniert bei mir besser:

Einfach:

ApplicationController.helpers.my_helper_method

Fortschritt:

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

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


1
Das ApplicationController.master_helper_modulegibt es in Rails 3 und 4 nicht mehr. Das ApplicationController.helpersist aber schön.
Samuel

Ich habe dafür gestimmt (die einfache Option), weil sie meinen Anforderungen entspricht. Ich benötige nur einen Helfer, der Informationen verwendet, die von einem Vorher-Filter in ApplicationController gespeichert wurden. In meinem Fall ist es also eine Erinnerung daran, dass eine Kopplung vorliegt, wenn die Zuordnung explizit angegeben wird. [Anwendungsfall ist eine Multi-Domain-App, die E-Mails über einen Modellbenachrichtiger mit einem URL-Link zurück zur App ausgibt - diese URL ändert sich je nach Domain der
Webanforderung

24

Um von Ihren eigenen Controllern aus auf Helfer zuzugreifen, verwenden Sie einfach:

OrdersController.helpers.order_number(@order)

2
Nur mit ApplicationController.helpers.order_number(@order). Das heißt, das order_numberwar amOrder Helper
ksugiarto

3
@rowanu Er sagt "Zugriff (Helfer von Ihren eigenen Controllern)", nicht "(Zugriff auf Helfer) von Ihren eigenen Controllern".
Ajedi32

11

Ich würde keine dieser Methoden empfehlen. Platzieren Sie es stattdessen in einem eigenen 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

Wenn Sie das my_helper_methodInnere eines Modells verwenden möchten , können Sie schreiben:

ApplicationController.helpers.my_helper_method
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.