9

我的应用程序应该呈现 html,以便在用户单击 ajax-link 时进行响应。

我的控制器:

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

4

3 回答 3

15

助手只是 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
于 2010-04-07T08:35:16.617 回答
13

好。让我们回顾一下。您希望访问确定的函数/方法,但不希望将这些方法附加到当前对象。

所以你想制作一个代理对象,它将代理/委托给这些方法。

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

,正如达米安指出的那样。

更新:您收到“url_for”错误的原因是您无权访问控制器的上下文,如上所述。您可以强制将控制器作为参数传递(Java 风格;)),例如:

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

然后,在你的助手中:

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

或事件更大的黑客,在此处介绍。但是,我会推荐将方法设为私有并将它们包含在控制器中的解决方案。

于 2010-04-07T13:38:04.310 回答
-1

拿着它!http://apotomo.de/2010/04/activehelper-rails-is-no-pain-in-the-ass/

这正是你要找的东西,伙计。

于 2010-04-10T18:20:34.727 回答