web-dev-qa-db-fra.com

NoMethodError lors d'une tentative d'appel de la méthode d'assistance à partir du contrôleur Rails

Je reçois une NoMethodError lorsque j'essaie d'accéder à une méthode définie dans l'un de mes modules d'assistance à partir de l'une de mes classes de contrôleur. L'application My Rails utilise la méthode de classe helper avec le symbole :all comme indiqué ci-dessous:

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

D'après ce que je comprends, cela devrait obliger toutes mes classes de contrôleur à inclure automatiquement tous les modules d'assistance dans le répertoire app/helpers, et donc à mélanger toutes les méthodes dans les contrôleurs. Est-ce correct?

Si j’ai explicitement include le module auxiliaire de l’automate, tout fonctionne correctement.

71
John Topley

helper :all rend toutes les aides (oui, toutes) disponibles dans les vues, il ne les inclut pas dans le contrôleur.

Si vous souhaitez partager du code entre l’assistant et le contrôleur, ce qui n’est pas très souhaitable car l’assistant est un code d’interface utilisateur et le contrôleur est un code de contrôleur, vous pouvez inclure l’assistant dans le contrôleur ou créer un module séparé et l’inclure dans le contrôleur et l'aide également.

49
Honza

Pour utiliser les méthodes d'assistance déjà incluses dans le moteur de modèle:

  • Rails 2: utilisez la variable @template
  • Rails 3: utilise la méthode du contrôleur Nice view_context

Exemple d'utilisation de l'appel 'number_to_currency' dans une méthode de contrôleur:

# 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
133
gamecreature

si vous avez besoin de partager une méthode entre un contrôleur et helper/view, vous pouvez simplement définir via 'helper_method' en haut du contrôleur:

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

  def my_shared_method
    #do stuff
  end
end

j'espère que cela pourra aider

30
ben

Méthodes d'assistance des contrôleurs

Une façon d'obtenir vos méthodes d'assistance consiste simplement à inclure votre fichier d'assistance.

include LoginHelper
cool_login_helper_method(x,y,z)

Cela met toutes les méthodes de ce module d'assistance à la portée de votre contrôleur. Ce n'est pas toujours une bonne chose. Pour que la portée reste séparée, créez un objet, insérez-lui les pouvoirs de cette aide et utilisez-le pour appeler les méthodes:

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

Helper: tous

helper :all rend toutes vos méthodes d'assistance de tous vos modules d'assistance disponibles pour tous vos views , mais cela ne fait rien pour vos contrôleurs. En effet, les méthodes d'assistance sont conçues pour être utilisées dans les vues et ne doivent généralement pas être accessibles à partir de contrôleurs. Dans les nouvelles versions de Rails, cette option est toujours activée par défaut pour chaque contrôleur.

28
Adrian Dunston

Pour Rails 3, utilisez la méthode view_context dans votre contrôleur:

def foo
  view_context.helper_method
  ...

Voici un exemple: http://www.christopherirish.com/2011/10/13/no-view_context-in-Rails-3-1-changes/

7
B Seven

Il est probablement plus propre d’utiliser la méthode helpers :

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

Le moment où je trouve que cela est le plus nécessaire est celui de l'écriture du flash ou des vérificateurs d'erreur personnalisés. Il est agréable d'utiliser des éléments tels que link_to helpers dans le message flash dans certaines circonstances. J'utilise la solution suivante pour obtenir des aides ActionView dans le contrôleur. Comme cela a été mentionné ci-dessus, cela brise la séparation MVC. Si quelqu'un d'autre a une meilleure idée, faites le moi savoir!

Sous ApplicationController, ajoutez ceci:

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

et à l'intérieur du ApplicationController, ajoutez

def foo
  Something.instance
end

et enfin, dans le contrôleur où vous voulez accéder au code d'assistance:

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

J'espère que cela contribue de quelque façon!

5
Scott Miller

Tous les assistants sont accessibles à l’aide de la variable @template du contrôleur.

@ template.my_super_helper

4
BitOfUniverse

Le contrôleur ne peut pas accéder automatiquement aux méthodes d'assistance. Nous devons les inclure dans le contrôleur de l'application.

module ApplicationHelper

 def hello_message
    "Hello World"
 end

fin

classe ApplicationController <ActionController :: Base

  include ApplicationHelper

  def message
     hello_message
  end

fin

3
Nitin

Les assistants doivent être utilisés avec des modèles, c.-à-d. vues, pas dans les contrôleurs. C'est pourquoi vous ne pouvez pas accéder à la méthode. Si vous souhaitez partager une méthode entre deux contrôleurs, vous devez la définir dans ApplicationController, par exemple. helper: all indique que toute méthode que vous définissez dans un fichier d'assistance du répertoire app/helpers sera disponible pour tous les modèles.

2
Milan Novota

Il existe deux façons de procéder: créer un module ou utiliser la variable @template. Consultez cette page pour plus de détails http://www.shanison.com/?p=305

1
Shanison

Si vous modifiez votre fichier application_controller.rb en ceci ...

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

... alors tous les assistants seront disponibles pour tous les contrôleurs.

0
I_do_python

Si vous avez seulement ApplicationHelper dans votre dossier app/helpers, vous devez le charger dans votre contrôleur avec include ApplicationHelper. Par défaut, Rails charge uniquement le module d'assistance portant le même nom que votre contrôleur. (par exemple, ArticlesController chargera ArticlesHelper). Si vous avez plusieurs modèles (articles, publications, catégories, par exemple), vous devez les télécharger tous dans votre contrôleur. les docs

Assistant

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

Exemple de contrôleur

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
0