2010-04-07 66 views
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與大量的方法

回答

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 

主要缺點這種方法是從輔助功能,您將無法訪問控制器上下文(例如,您將無法訪問PARAMS ,會話等)

一個妥協方法是將這些函數聲明爲輔助模塊中的私有函數,因此,當您將包含模塊時,它們也將在控制器類中是私有的。

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 

或事件更大的黑客,提出here。不過,我會推薦解決方案,將方法隱藏起來並將它們包含在控制器中。

+0

是的,我已經嘗試了你的第一個方法,但我得到了:NoMethodError(未定義的方法'url_for'爲零:NilClass)。我認爲,幫助程序模塊無法訪問ActionView的幫助程序 – FancyDancy 2010-04-07 20:12:27

+0

Yap,您必須有權訪問控制器的上下文。 – 2010-04-07 20:37:08

+0

我更新了我的回覆,以考慮到您所說的內容。 – 2010-04-07 20:52:51

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 
+0

我不想包含整個用戶幫助。如果我這樣做,UserController將使這些方法可以通過GET -/users/link_to_profile請求它們。我可以創建自定義類,但是我應該包含哪些內容以獲取方法「url_for」? – FancyDancy 2010-04-07 10:53:39

+3

您不能僅包含模塊中的一種方法。 僅使用控制器中包含的方法創建新幫手。 並將這些方法包含爲私有的,這樣它們將不會從http請求中訪問。 – 2010-04-07 11:56:17

相關問題