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 эта опция всегда включена для каждого контроллера по умолчанию.
Ответ 5
Для Rails 3 используйте метод view_context
в вашем контроллере:
def foo
view_context.helper_method
...
Вот пример: http://www.christopherirish.com/2011/10/13/no-view_context-in-rails-3-1-changes/
Ответ 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) %>
из любого представления в вашем приложении.