Мои вспомогательные методы в контроллере - PullRequest
9 голосов
/ 07 апреля 2010

Мое приложение должно отображать HTML, чтобы ответить, когда пользователь нажимает ajax-ссылку.

Мой контроллер:

def create_user
  @user = User.new(params)
  if @user.save
    status = 'success'
    link = link_to_profile(@user) #it's my custom helper in Application_Helper.rb
  else
    status = 'error'
    link = nil
  end

  render :json => {:status => status, :link => link}
end

Мой помощник:

  def link_to_profile(user)
    link = link_to(user.login, {:controller => "users", :action => "profile", :id => user.login}, :class => "profile-link")
    return(image_tag("/images/users/profile.png") + " " + link)
  end

Я пробовал такие методы:

ApplicationController.helpers.link_to_profile(@user)
# It raises: NoMethodError (undefined method `url_for' for nil:NilClass)

и

class Helper
  include Singleton
  include ActionView::Helpers::TextHelper
  include ActionView::Helpers::UrlHelper
  include ApplicationHelper
end
def help
  Helper.instance    
end

help.link_to_profile(@user)
# It also raises: NoMethodError (undefined method `url_for' for nil:NilClass)

Кроме того, да, я ЗНАЮ о: helper_method, и это работает, но я не хочу перегружать мой ApplicationController множеством этих методов

Ответы [ 3 ]

15 голосов
/ 07 апреля 2010

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

module UserHelper
    def link_to_profile(user)
        link = link_to(user.login, {:controller => "users", :action => "profile", :id => user.login}, :class => "profile-link")
        return(image_tag("/images/users/profile.png") + " " + link)
    end
end

А в вашем контроллере:

class UserController < ApplicationController
    include UserHelper

    def create
        redirect_to link_to_profile(User.first)
    end
end
13 голосов
/ 07 апреля 2010

Oki.Давайте подведем итоги.Вам нужен доступ к определенным функциям / методам, но вы не хотите, чтобы эти методы были присоединены к текущему объекту.

Итак, вы хотите создать прокси-объект, который будет прокси / делегировать этим методам.

class Helper
  class << self
   #include Singleton - no need to do this, class objects are singletons
   include ApplicationHelper
   include ActionView::Helpers::TextHelper
   include ActionView::Helpers::UrlHelper
   include ApplicationHelper
  end
end

И в контроллере:

class UserController < ApplicationController
  def your_method
    Helper.link_to_profile
  end
end

Основной недостатокэтот подход заключается в том, что из вспомогательных функций у вас не будет доступа к контексту контроллера (например, у вас не будет доступа к параметрам, сеансам и т. д.)

Компромиссом будет объявление этих функций частными ввспомогательный модуль, поэтому, когда вы включите модуль, они также будут частными в классе контроллера.

module ApplicationHelper
  private
  def link_to_profile
  end
end

class UserController < ApplicationController
  include ApplicationHelper
end

, как указано Damien .

Обновление : причина, по которой вы получаете ошибку 'url_for', заключается в том, что у вас нет доступа к контексту контроллера, как указано выше.Вы можете принудительно передать контроллер в качестве параметра (в стиле Java;)), например:

Helper.link_to_profile(user, :controller => self)

, а затем, в вашем помощнике:

def link_to_profile(user, options)
  options[:controller].url_for(...)
end

или событие большего взлома, представленное здесь .Однако я бы порекомендовал это решение, сделав методы приватными и включив их в контроллер.

0 голосов
/ 10 апреля 2010

Возьми это!http://apotomo.de/2010/04/activehelper-rails-is-no-pain-in-the-ass/

Это именно то, что вы искали, чувак.

...