2010-04-07 8 views
9

Mi aplicación debe mostrar html, para responder cuando un usuario hace clic en ajax-link.Mis métodos de ayuda en el controlador

Mi controlador:

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 

Mi ayudante:

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 

He tratado de este tipo de métodos:

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

y:

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) 

Además, sí, LO SÉ: helper_method, y funciona, pero no quiero sobrecargar mi ApplicationController con muchos de esos métodos

Respuesta

13

Oki. Recapitulemos. Desea acceder a funciones/métodos de certaint, pero no desea que esos métodos se adjunten al objeto actual.

Así que quiere hacer un objeto proxy, que delegará/delegará esos métodos.

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 

Y, en el controlador:

class UserController < ApplicationController 
    def your_method 
    Helper.link_to_profile 
    end 
end 

La principal desventaja de este enfoque es que a partir de las funciones de ayuda que no tendrá acceso al controlador de contexto (EG que no tendrá acceso a los parametros , sesión, etc.)

Un compromiso sería declarar esas funciones como privadas en el módulo auxiliar, por lo tanto, cuando se incluya el módulo, también serán privadas en la clase de controlador.

module ApplicationHelper 
    private 
    def link_to_profile 
    end 
end 

class UserController < ApplicationController 
    include ApplicationHelper 
end 

, como Damien señalado.

Actualización: El motivo por el que aparece el error 'url_for' es que no tiene acceso al contexto del controlador, como se indicó anteriormente. Se podría obligar a pasar el controlador como parámetro (al estilo de Java;)) como:

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

y luego, en su ayudante:

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

o evento un corte más grande, presentó here. Sin embargo, recomendaría la solución haciendo que los métodos sean privados y los incluya en el controlador.

+0

Sí, probé su primer método, pero obtuve: NoMethodError (método indefinido 'url_for 'para nil: NilClass). Creo que el módulo auxiliar no puede acceder a los ayudantes de ActionView – FancyDancy

+0

Yap, debe tener acceso al contexto del controlador. –

+0

Actualicé mi respuesta para tomar en consideración lo que dijo. –

15

helpers son solo módulos ruby ​​que puedes incluir en cualquier controlador solo como cualquier módulo

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 

Y, en su controlador:

class UserController < ApplicationController 
    include UserHelper 

    def create 
     redirect_to link_to_profile(User.first) 
    end 
end 
+0

no quiero incluir a todo el usuario. Y si hago esto, UserController pondrá esos métodos a disposición para solicitarlos a través de GET -/users/link_to_profile. Puedo hacer clases personalizadas, pero ¿qué debo incluir para obtener el método "url_for"? – FancyDancy

+3

No puede incluir solo un método de un módulo. Crea un nuevo ayudante con solo los métodos que quieras incluir en el controlador. E incluya estos métodos como privados para que no se pueda acceder a ellos desde las solicitudes http. –

Cuestiones relacionadas