Pregunta

I wrote an app to get the last_insurance value and sum but I'm getting "undefined method `total' for nil:NilClass" in my view.

My tables are:

|policies|
  ID    POLICY_NUM  DELETED    STATE    POLICY_BUSINESS_UNIT_ID
   1    1234           0         0            1
   2    5678           0         1            1
   3    3444           0         0            2           
   4    4577           0         1            2 

|insurances|
  ID    POLICY_ID   NET_INSURANCE   TYPE_MONEY 
   1        1               300        1
   2        1               400        2
   3        1               100        1
   4        2               400        1
   5        2               800        2
   6        3               100        1
   7        3               400        2
   8        4               800        2
   9        2               900        1

I have lot of information but this is little description:

http://sqlfiddle.com/#!2/ed2dd/4

Here my models:

 class Policy < ActiveRecord::Base
   has_many :insurances
 end

 class Insurance < ActiveRecord::Base
   belongs_to :policy
 end

This is my controller:

class PolicyController < ApplicationController
     def calculator

        @business = PolicyBusinessUnit.find(:all)

        @euros = Policy.find_by_sql(["SELECT i1.type_money, SUM( i1.net_insurance ) total
        FROM (SELECT MAX( id ) id FROM insurances GROUP BY policy_id)i2
        JOIN insurances i1 USING ( id ) 
        JOIN policies p ON p.id = i1.policy_id
        WHERE i1.type_money = 2 
        AND p.deleted= 0 
        AND p.policy_business_unit_id = ? AND p.state = ?
        GROUP BY i1.type_money" ,params[:busi].to_i,params[:state].to_i  ])
     end
end

This is my view showing my status in a combobox:

  <% form_tag :controller=>"policy",:action=>"calculator" do %>
      Business:
      <%= select_tag "busi",options_for_select(@business.collect {|t| [t.name.to_s,t.id]},  params[:busi].to_i ) %>

      Status:
      <%= select_tag "state",options_for_select([ ["OK",0],["CANCEL",1] ],params[:state].to_i) %>
      <%= submit_tag "SEARCH", :name => nil %>
  <% end %>

  Sum Euros:
  <input id="euros" readonly="readonly" value="<%= @euros[0].total"/>

And I'm getting this message:

  undefined method `total' for nil:NilClass

But, when I tried this it's working fine when I don't use params[busi]:

    @dolares= Policy.find_by_sql(["SELECT sum(i1.net_insurance) total 
        FROM (SELECT max(id) id FROM insurances GROUP BY policy_id)i2
        JOIN insurances i1 USING (id)
        JOIN policies p ON p.id = i1.policy_id
        WHERE i1.type_money = 2 
        AND p.deleted= 0 
        AND p.policy_business_unit_id = 2 AND p.state = ?
        GROUP BY i1.type_money" , params[:state].to_i  ])

Another thing, when I removed total here and I used my controller with 2 params:

    @dolares= Policy.find_by_sql(["SELECT sum(i1.net_insurance) total 
        FROM (SELECT max(id) id FROM insurances GROUP BY policy_id)i2
        JOIN insurances i1 USING (id)
        JOIN policies p ON p.id = i1.policy_id
        WHERE i1.type_money = 2 
        AND p.deleted= 0 
        AND p.policy_business_unit_id = ? AND p.state = ?
        GROUP BY i1.type_money" , params[:busi].to_i,params[:state].to_i  ])

   <input id="euros" readonly="readonly" value="<%= @euros[0]"/>

I GOT #<Policy:0x7f41d09909d0>.

After that i added 'total' again and i got the value without problems

   <input id="euros" readonly="readonly" value="<%= @euros[0].total"/>

Maybe I need to add a conditional? What is wrong?

¿Fue útil?

Solución

Well @carlitos according to your last edition you're getting nil values because it has 0. So to not show the error you need to try this:

<input id="euros" readonly="readonly" value="<%= @euros[0].try(:total)"/>

This will hide the error and will show 0 when the sum is nil.

Otros consejos

Undoubtedly, the SQL code you are running is returning no data for the value in params[:state]. You can test this out by running the SQL directly from console.

For the record, you can perform the same query using the query API:

sub_query = Insurance.group(:policy_id).
                      select('MAX(insurances.id)').to_sql
Insurance.joins(:policy).where("insurances.id IN (#{sub_query})").
                         where(type_money: 2).
                         where(policies: {deleted: 0, 
                                          policy_business_unit_id: params[:busi].to_i,
                                          state: params[:state].to_i }).
                         sum(:net_insurance)

Once you solve your nil problem, you may find you hit upon a second issue: Since you find_by_sql, you may not get the convenience of Active Record bindings. I have had this problem when joining from multiple tables and otherwise creating complex SQL.

Try:

@euros[0]['total']

I can't take the time to reimplement your situation to test this but I presume the SQL method uses a hash structure for the result. If not, just print to debug/inspect the object to see its structure and determine how to reference it.

At worst you may need to say:

@euros[0][1]

since total is the second item of each row in the SQL results.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top