Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My helper methods in controller

My app should render html, to answer when a user clicks ajax-link.

My controller:

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

My helper:

  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

I have tried such methods:

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

and:

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)

In addition, yes, I KNOW about :helper_method, and it works, but i don't want to overload my ApplicationController with a plenty of that methods

like image 353
Alex Avatar asked Apr 07 '10 08:04

Alex


People also ask

What are helper methods?

A helper method is a small utility function that can be used to extract logic from views and controllers, keeping them lean. Views should never have logic because they're meant to display HTML. In addition, there's no way to test view logic, but if we extract this logic into methods it can then be tested.

Can we use helper method in controller Rails?

In Rails 5, by using the new instance level helpers method in the controller, we can access helper methods in controllers.

Can we call controller method in Helper?

You generally don't call controller-methods from helpers. That is: if you mean a method that collects data and then renders a view (any other method that needs to be called should probably not be in a controller). It is definitely bad practice and breaks MVC.

What are helper methods in Rails?

A helper is a method that is (mostly) used in your Rails views to share reusable code. Rails comes with a set of built-in helper methods. One of these built-in helpers is time_ago_in_words . This method is helpful whenever you want to display time in this specific format.


2 Answers

helpers are just ruby modules which you can include in any controller just like any module.

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

And, in your controller :

class UserController < ApplicationController
    include UserHelper

    def create
        redirect_to link_to_profile(User.first)
    end
end
like image 145
Damien MATHIEU Avatar answered Sep 29 '22 11:09

Damien MATHIEU


Oki. Let's recap. You want access to certaint functions/methods, but you don't want those methods to be attached to current object.

So you want to make a proxy object, that will proxy/delegate to those methods.

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

And, in controller:

class UserController < ApplicationController
  def your_method
    Helper.link_to_profile
  end
end

The main disadvantage to this approach is that from the helper functions you won't have access to controller context (EG you won't have access to params, session, etc)

A compromise would be to declare those functions as private in the helper module, therefore, when you will include the module, they will also be private in the controller class.

module ApplicationHelper
  private
  def link_to_profile
  end
end

class UserController < ApplicationController
  include ApplicationHelper
end

, as Damien pointed out.

Update: The reason why you get the 'url_for' error is that you do not have access to controller's context, as stated above. You could force passing the controller as a parameter(Java-style ;) ) like:

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

and then, in your helper:

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

or event a bigger hack, presented here. However, i would reccomend the solution with making methods private and including them in the controller.

like image 42
Vlad Zloteanu Avatar answered Sep 29 '22 10:09

Vlad Zloteanu