Jenny Blunt
Jenny Blunt

Reputation: 1596

Can't call calculated field rails3

I have a really simple cost model which belongs to an order.

Each cost has a value and quantity and I'm calculating the total using:

def set_total
    @set_total = quantity * amount
end

This works great and in my costs views, I can call with:

<td><%= number_to_currency(cost.set_total, :unit => "&pound;") %></td>

However, I don't seem to be able to show this in my orders show view - get a NoMethodError:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.*

In orders, show, I have this:

<% unless @order.costs.empty? %>
<% @order.costs.each do |cost| %>  
    <%= cost.description %>
    <%= cost.cost_type %>
    <%= number_to_currency(cost.amount, :unit => "&pound;") %>
    <%= cost.quantity %>
    <%= cost.set_total %>     
<% end %>
<% end %>

My routes are setup fine:

resources :orders do
  :costs
end

If I use a table to display the information, I get a blank line at the end. Costs partial:

 <% unless @order.costs.empty? %>
        <table border='1' cellpadding="5">
          <tr>
            <th>Description</th>
            <th>Type</th>
            <th>Amount</th>
            <th>Quantity</th>
            <th>Total</th>

          </tr>
        <% @order.costs.each do |cost| %> 
          <tr>
            <td><%= cost.description %></td>
            <td><%= cost.cost_type %></td>
            <td><%= number_to_currency(cost.amount, :unit => "&pound;") %></td>
        <td><%= cost.quantity %></td>   
        <td><%= cost.set_total %></td>  

          </tr>
        <% end %>
        </table>
        <% end %>

Can see an extra table row at the bottom and can't see why. Think this is leading to the nil value.

--edit--

With debugging on, I can still see extra lines:

!ruby/ActiveRecord:Cost 
  attributes: 
    description: 
    cost_type: 
    amount: 
    order_id: 14
    code: 
    created_at: 
    updated_at: 
    quantity: 

Which doesn't make sense because I've just reset the db... Why is a blank cost created, with no ID even.

UPDATE

class CostsController < ApplicationController
  before_filter :authenticate_user!
  load_and_authorize_resource
  def index
    @costs = Cost.paginate(:per_page => 3, :page => params[:page])
    respond_to do |format|
        format.html # index.html.erb
        format.xml  { render :xml => @costs }
  end
  end

  def show
        @costs = Cost.find(params[:id])
    end

  def new
  end

  def edit
  end
  def create
      @order = Order.find(params[:order_id])
      @cost = @order.costs.create(params[:cost])
      redirect_to order_path(@order)
    end
end

Upvotes: 0

Views: 331

Answers (3)

Adrien Coquio
Adrien Coquio

Reputation: 4930

Could you please post your controller code ?
I would think that you build a new cost in your controller, using something like @orders.costs.new or @orders.costs.build ?
Your last comment about the table showing even if there are no cost for this order validate this hypothesis

UPDATE:

Also for the method set_total, you should consider to refactor it to :

def total
  @total ||= quantity.to_i * amount
end

Using this code the total value will be cached for other called to total on this object.
Using total instead of set_total for the name of the method is more close to the ruby/rails convention.

Upvotes: 1

loosecannon
loosecannon

Reputation: 7803

There is something up with your costs.

when you create then are you using @order.costs.new(....) make sure you save them after that, that could be the problem.

Try using the console to create and play with an object, see if it is failing validation, not saving etc

Upvotes: 0

BitOfUniverse
BitOfUniverse

Reputation: 6021

The error occurred while evaluating nil.* that error mean that you trying to call * method on the nil object.

def set_total
 @set_total = quantity * amount
end

Make sure that quantity attribute is set to not nil value for each Cost record.

or change your method to:

def set_total
 @set_total = (quantity || 0) * amount
end

Upvotes: 1

Related Questions