tmaximini
tmaximini

Reputation: 8503

rails "undefined method" when invoking a helper method from layout view

I have an helper method in to get the current shopping cart in my application controller:

class ApplicationController < ActionController::Base
  protect_from_forgery

  helper :all # include all helpers, all the time

  private

  def current_cart
    if session[:cart_id]
      @current_cart ||= Cart.find(session[:cart_id])
      session[:cart_id] = nil if @current_cart.purchased_at
    end
    if session[:cart_id].nil?
      @current_cart = Cart.create!
      session[:cart_id] = @current_cart.id
    end
    @current_cart
  end

end

I can call the method from most of my views, but I want to use it in the views/layout/application.html.erb file, like this:

<div id="cart_menu">
    <ul>
    <li>
      <%= image_tag("cart.jpg")%>
    </li>
    <li>
      <%= link_to "#{current_cart.number_of_items}", current_cart_url %>
    </li>
    <li>
          <a href="/checkout/">Checkout</a>
        </li>
    </ul>
</div>

But when I try that, I get an

undefined local variable or method `current_cart' for #<#<Class:0x2d2d834>:0x2d2b908>

error..

Any ideas whyis that?

Upvotes: 6

Views: 13290

Answers (4)

BitOfUniverse
BitOfUniverse

Reputation: 6011

Add helper_method :current_cart to your application controller.

class ApplicationController < ActionController::Base
  protect_from_forgery
  helper_method :current_cart
  ...
end

Upvotes: 8

Adrien Coquio
Adrien Coquio

Reputation: 4930

Your example fail because you define the method current_cart in the ApplicationController but controller method are not accessible in the view.

There are two ways to achieve what you want :

The first way is to move the method current_cart in an helper.

The second way will be to set the variable @current_cart with a before_filter and use @current_cart in the view, see below :

class ApplicationController < ActionController::Base
  protect_from_forgery

  helper :all # include all helpers, all the time

  before_filter :set_current_cart

  private

  def set_current_cart
    if session[:cart_id]
      @current_cart ||= Cart.find(session[:cart_id])
      session[:cart_id] = nil if @current_cart.purchased_at
    end
    if session[:cart_id].nil?
      @current_cart = Cart.create!
      session[:cart_id] = @current_cart.id
    end
  end

end

In your view :

<%= link_to "#{@current_cart.number_of_items}", current_cart_url %>

Upvotes: 8

bassneck
bassneck

Reputation: 4043

I'm actually not sure, why this works in other views, but I think, as a site-wide logic, you should define it as a before_filter for ApplicationController. If you only need it in one controller, put it there.

And it's not a "helpers". Helpers are stored in app/helpers and are usually used to simplify views by hiding some html inside it's methods.

Upvotes: 0

Micha&#235;l Witrant
Micha&#235;l Witrant

Reputation: 7714

Helper methods belong to the helper modules, e.g. in app/helpers/application_helper.rb

Upvotes: 0

Related Questions