NoMethodError beim Versuch, die Hilfsmethode vom Rails-Controller aus aufzurufen

74

Ich bin immer ein , NoMethodErrorwenn versucht wird, ein Verfahren in einem meiner Helfer - Module von einem meiner Controller - Klassen definiert zuzugreifen. Meine Rails-Anwendung verwendet die helperKlassenmethode mit dem folgenden :allSymbol:

class ApplicationController < ActionController::Base
  helper :all
  .
  .
end

Ich verstehe, dass dies dazu führen sollte, dass alle meine Controller-Klassen automatisch alle Hilfsmodule im Verzeichnis app / helpers enthalten und daher alle Methoden in die Controller einmischen. Ist das richtig?

Wenn ich explizit includedas Hilfsmodul in der Steuerung habe, dann funktioniert alles richtig.

John Topley
quelle
Erbt der betreffende Controller von ApplicationController?
Michael Sepcot
Ja. Ich habe das Problem bei zwei Controllern, die die betreffende Methode verwenden, und beide Controller erben von ApplicationController.
John Topley

Antworten:

50

helper :all stellt alle Helfer (ja, alle) in den Ansichten zur Verfügung, schließt sie nicht in den Controller ein.

Wenn Sie einen Code zwischen Helfer und Controller freigeben möchten, was nicht sehr wünschenswert ist, da Helfer UI-Code und Controller Controller-Code ist, können Sie entweder den Helfer in den Controller aufnehmen oder ein separates Modul erstellen und diesen einbinden der Controller und der Helfer.

Honza
quelle
1
Danke, das macht Sinn. Ich habe einen Code, den ich zwischen zwei Controllern teilen möchte. Ich werde ein neues Modul erstellen und das einschließen.
John Topley
Das ist in der Tat der beste Ansatz
Ggomeze
2
Geht es wirklich darum, zwischen zwei Controllern zu teilen? Oder zwischen Controller und Ansicht? Ich denke das letztere. Der Weg von gamecreature (@template, view_context) sieht für mich also richtig aus.
Pascal
Meine funky Redirect-Methoden sind in Helfern. Ich brauche sie von meinen Controllern. Ich finde das nicht schlecht.
Victor Pudeyev
2
Sie sagen, es ist unerwünscht, Hilfsmethoden in den Controller aufzunehmen, da UI-Code und Controller-Code getrennt sein sollten. Was aber, wenn Sie filtern und offensichtlich auf den Parameter-Hash in der Steuerung und Ansicht zugreifen müssen und manchmal Methoden in der Ansicht und der Steuerung aufrufen müssen, um auf Parameter-Variablen zuzugreifen. Was würden Sie unter diesen Umständen tun?
JohnMerlino
133

So verwenden Sie die bereits in der Vorlagen-Engine enthaltenen Hilfsmethoden:

  • Schienen 2: Verwenden Sie die @templateVariable.
  • Rails 3: hat die nette Controller-Methode view_context

Beispiel für die Verwendung des Aufrufs von 'number_to_currency' in einer Controller-Methode:

# rails 3 sample
def controller_action
  @price = view_context.number_to_currency( 42.0 ) 
end

# rails 2 sample
def controller_action
  @price = @template.number_to_currency( 42.0 ) 
end
Spielkreatur
quelle
3
Dies ist die beste Antwort der Gruppe - sollte oben sein
Obie
8
Für Schienen 3. DAS IST DIE ANTWORT.
Juanin
Keine Erklärung für die Verwendung view_context.
Sarah Vessels
3
Eine andere Lösung (funktioniert in beiden Rails-Versionen) ist die Verwendung von: ApplicationController.helpers.number_to_currency (
42.0
30

Wenn Sie eine Methode zwischen einem Controller und einem Helfer / einer Ansicht freigeben müssen, können Sie diese einfach über 'helper_method' oben im Controller definieren:

class ApplicationController < ActionController::Base
  helper_method :my_shared_method
  ...

  def my_shared_method
    #do stuff
  end
end

hoffentlich hilft das

ben
quelle
2
Die Zeile helper_method :my_shared_methodmuss nicht "oben" sein. Sie kann überall hingehen und gefällt mir am besten direkt über der Definition ( def my_shared_method).
user664833
28

Hilfsmethoden von Controllern

Eine Möglichkeit, an Ihre Hilfsmethoden heranzukommen, besteht darin, einfach Ihre Hilfsdatei einzuschließen.

include LoginHelper
cool_login_helper_method(x,y,z)

Dadurch werden alle Methoden dieses Hilfsmoduls in Ihrem Controller berücksichtigt. Das ist nicht immer gut. Um den Bereich getrennt zu halten, erstellen Sie ein Objekt, geben Sie ihm die Fähigkeiten dieses Helfers und rufen Sie damit die folgenden Methoden auf:

login_helper = Object.new.extend(LoginHelper)
login_helper.cool_login_helper_method(x,y,z)

Helfer: alle

helper :allstellt alle Ihre Hilfsmethoden aus all Ihren Hilfsmodulen für alle Ihre Ansichten zur Verfügung , tut jedoch nichts für Ihre Controller. Dies liegt daran, dass Hilfsmethoden für die Verwendung in Ansichten entwickelt wurden und im Allgemeinen nicht von Controllern aus aufgerufen werden sollten. In neueren Versionen von Rails ist diese Option standardmäßig immer für jeden Controller aktiviert.

Adrian Dunston
quelle
5

Die Zeit, in der dies am dringendsten benötigt wird, ist das Schreiben des Flashs oder der benutzerdefinierten Fehlerprüfungen. Unter bestimmten Umständen ist es schön, Dinge wie link_to-Helfer in der Flash-Nachricht zu verwenden. Ich verwende die folgende Lösung, um ActionView-Helfer in den Controller zu integrieren. Beachten Sie, dass dies, wie oben erwähnt, die MVC-Trennung unterbricht. Wenn also jemand eine bessere Idee hat, lassen Sie es mich wissen!

Fügen Sie unter ApplicationController Folgendes hinzu:

class Something
  include Singleton
  include ActionView::Helpers::UrlHelper
end

und fügen Sie im ApplicationController hinzu

def foo
  Something.instance
end

und schließlich in der Steuerung, in der Sie auf den Hilfecode zugreifen möchten:

messages << "<li class='error'>Your have an Error!<%= foo.link_to('Fix This', some_path) %></li>"

Hoffe das hilft irgendwie!

Scott Miller
quelle
5

Es ist wahrscheinlich sauberer, die Hilfsmethode zu verwenden:

class FooController < ActionController::Base
  def action
    self.class.helpers.helper_method arg
  end
end
Antonio Tapiador
quelle
4

Auf jeden Helfer kann mit der Variablen @template im Controller zugegriffen werden.

@ template.my_super_helper

BitOfUniverse
quelle
3

Der Controller kann nicht automatisch auf Hilfsmethoden zugreifen. Wir müssen sie in den App-Controller aufnehmen.

Modul ApplicationHelper

 def hello_message
    "Hello World"
 end

Ende

Klasse ApplicationController <ActionController :: Base

  include ApplicationHelper

  def message
     hello_message
  end

Ende

Nitin
quelle
2

Helfer sind mit Vorlagen zu verwenden, dh. Ansichten, nicht in Controllern. Deshalb können Sie nicht auf die Methode zugreifen. Wenn Sie eine Methode für zwei Controller freigeben möchten, müssen Sie sie beispielsweise in ApplicationController definieren. helper: Alle sagen, dass jede Methode, die Sie in einer Hilfedatei im Verzeichnis app / helpers definieren, für jede Vorlage verfügbar ist.

Milan Novota
quelle
1

Es gibt zwei Möglichkeiten, dies zu tun: entweder um ein Modul zu erstellen oder die Variable @template zu verwenden. Weitere Informationen finden Sie unter http://www.shanison.com/?p=305

Shanison
quelle
1

Wenn Sie Ihre Datei application_controller.rb in diese ändern ...

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  include SessionsHelper
end

... dann stehen alle Helfer allen Controllern zur Verfügung.

I_do_python
quelle
0

Wenn Sie nur ApplicationHelper in Ihrem app/helpersOrdner haben, müssen Sie es mit in Ihren Controller laden include ApplicationHelper. Standardmäßig lädt Rails nur das Hilfsmodul, das denselben Namen wie Ihr Controller hat. (zB ArticlesController lädt ArticlesHelper). Wenn Sie viele Modelle haben (z. B. Artikel, Beiträge, Kategorien), müssen Sie jedes Modell in Ihren Controller hochladen. die docs

Helfer

module PostsHelper
    def find_category(number)
        return 'kayak-#{number}'
    end
    def find_other_sport(number)
        "basketball" #specifying 'return' is optional in ruby
    end
end

module ApplicationHelper
    def check_this_sentence
        'hello world'
    end

end

Beispiel Controller

class ArticlesController < ApplicationController
    include ApplicationHelper
    include PostsHelper
    #...and so on...

  def show#rails 4.1.5
    #here I'm using the helper from PostsHelper to use in a Breadcrumb for the view
    add_breadcrumb find_other_sport(@articles.type_activite), articles_path, :title => "Back to the Index"
    #add_breadcrumb is from a gem ... 
    respond_with(@articles)
  end
end
Papouche Guinslyzinho
quelle
0

Bitte versuchen Sie es include SessionsHelperin ApplicationController

class ApplicationController < ActionController::Base
  include SessionsHelper
  ...
end
Prateek Arora
quelle