NoMethodError при попытке вызвать вспомогательный метод из контроллера Rails

Я получаю NoMethodError при попытке получить доступ к методу, определенному в одном из моих вспомогательных модулей, из одного из моих классов контроллера. Приложение My Rails использует метод класса helper с символом :all, как показано ниже:

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

Я понимаю, что это должно заставить все мои классы контроллеров автоматически включать все вспомогательные модули в каталог app/helpers, поэтому смешивание всех методов в контроллерах. Правильно ли это?

Если я явно include вспомогательный модуль в контроллере, тогда все работает правильно.

Ответ 1

helper :all делает все помощники (да, все они) доступными в представлениях, он не включает их в контроллер.

Если вы хотите поделиться каким-то кодом между хелпером и контроллером, что не очень желательно, потому что вспомогательный код UI и контроллер, ну, код контроллера, вы можете либо включить помощника в контроллер, либо создать отдельный модуль и включите это также в контроллер и помощник.

Ответ 2

Чтобы использовать вспомогательные методы, уже включенные в механизм шаблонов:

  • Rails 2: используйте переменную @template.
  • Rails 3: имеет хороший метод контроллера view_context

Пример использования вызова 'number_to_currency' в методе контроллера:

# 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

Ответ 3

если вам нужно разделить метод между контроллером и помощником/представлением, вы можете просто определить через "helper_method" в верхней части контроллера:

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

  def my_shared_method
    #do stuff
  end
end

надеюсь, что поможет

Ответ 4

Вспомогательные методы от контроллеров

Один из способов получить ваши вспомогательные методы - просто включить ваш вспомогательный файл.

include LoginHelper
cool_login_helper_method(x,y,z)

Приводит все методы из этого вспомогательного модуля в область вашего контроллера. Это не всегда хорошо. Чтобы разделить область, создать объект, наполнить его полномочиями этого помощника и использовать его для вызова методов:

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

Помощник: все

helper :all делает все ваши вспомогательные методы из всех ваших вспомогательных модулей доступными для всех ваших представлений, но он ничего не делает для ваших контроллеров. Это связано с тем, что вспомогательные методы предназначены для использования в представлениях и, как правило, не должны быть доступны из контроллеров. В новых версиях Rails эта опция всегда включена для каждого контроллера по умолчанию.

Ответ 6

Время, когда я нахожу это наиболее нужным, - это записать флеш-память или настраиваемые проверки ошибок. В некоторых случаях приятно использовать такие вещи, как link_to helpers во флэш-сообщении. Я использую следующее решение для получения помощников ActionView в контроллере. Имейте в виду, что, как упоминалось выше, это нарушает разделение MVC, поэтому, если кто-то еще имеет лучшую идею, дайте мне знать!

Ниже ApplicationController добавьте это:

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

и внутри ApplicationController добавьте

def foo
  Something.instance
end

и, наконец, в контроллере, где вы хотите получить доступ к вспомогательному коду:

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

Надеюсь, что это поможет в некотором роде!

Ответ 7

Вероятно, более чистый метод helpers:

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

Ответ 8

Любой помощник может быть доступен с помощью переменной @template в контроллере.

@template.my_super_helper

Ответ 9

Контроллер не может автоматически обращаться к вспомогательным методам. Мы должны включить их в контроллер приложения.

module ApplicationHelper

 def hello_message
    "Hello World"
 end

конец

class ApplicationController < ActionController:: Base

  include ApplicationHelper

  def message
     hello_message
  end

конец

Ответ 10

Помощники должны использоваться с шаблонами, т.е. а не в контроллерах. Вот почему вы не можете получить доступ к методу. Если вы хотите поделиться методом между двумя контроллерами, вы должны определить его в ApplicationController, например. helper: все говорят, что любой метод, который вы определяете в любом вспомогательном файле в каталоге app/helpers, будет доступен для любого шаблона.

Ответ 11

Есть два способа сделать это: либо создать модуль, либо использовать переменную @template. Проверьте это для получения более подробной информации. http://www.shanison.com/?p=305

Ответ 12

Если у вас есть только ApplicationHelper внутри вашей папки app/helpers, вы должны загрузить его в свой контроллер с помощью include ApplicationHelper. По умолчанию Rails загружает только вспомогательный модуль с тем же именем, что и ваш контроллер. (например, ArticlesController загрузит ArticlesHelper). Если у вас много моделей (например, "Статьи, посты", "Категории" ), вы должны загрузить каждый из них в своем контроллере. документы

Помощник

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

Пример контроллера

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

Ответ 13

Если вы измените файл application_controller.rb на этот...

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

... тогда все помощники будут доступны для всех контроллеров.

Ответ 14

Rails 5 обновление. Я столкнулся с подобной проблемой с представлениями, не выбирающими метод из application_helper.rb. Этот пост помог мне. Из того, что я могу собрать, файлы, которые предоставляются в папке помощника, предназначены только для этих представлений. Методы в application_helper не будут доступны автоматически для всех представлений. Чтобы создать вспомогательный метод, доступный для всех представлений, вам необходимо создать новый вспомогательный файл в каталоге помощников, например clean_emails.rb и добавить свой пользовательский метод здесь.

Module CleanEmails
  def clean_email(email)
     *do some stuff to email*
     return email
  end
end

Затем вы можете позвонить <%= clean_email(email) %> из любого представления в вашем приложении.