Treating nil as zero in sum function for a method-derived attribute (Rails 4.2)

I have a table that lists rental prices of a product in a table as number_to_currency(product.heritable_rental_price.to_f * product.quantity.to_f), from a Product model, where the percentage is derived from a default and the working value available for that product:

def heritable_rental_price
    if rental_price.present?
      return rental_price
    elsif working_value.present?
      return (working_value || 0.0) * heritable_rental_price_percentage / 100
    else  
      return nil
    end
  end

I'm using Treating nil as zero in sum function as a model to work this problem out.

def rental_price_sum
 self.map(&:heritable_rental_price).compact.sum
end   

Here's how it plays out in the view:

<tr>
<td>
 <% if product.heritable_rental_price.present? %>
  <%= number_to_currency(product.heritable_rental_price.to_f * product.quantity.to_f) %>
 <% else %>  
   --- 
 <%end%>
</td>
<td>
</tr>
<tr>
 <td>
  <% if product.heritable_rental_price.present? %>
    <%= number_to_currency((product.rental_price_sum.to_f * product.quantity.to_f).reduce(0, :+)) %>
  <% else %>  
    --- 
  <%end%>
</td>
</tr>

As for things I've also tried, I've been able to get the sum of the pre-defined :working_value out by adding .sum[:working_value] to the end of, but not this one, so far (since it's defined in the model, I can't pull it out by Sym)

Total Working Value: <%=number_to_currency(category.products_by_warehouse_id(params[:id]).sum(:working_value)) %>

1 answer

  • answered 2018-11-08 08:21 ReggieB

    First I'd point out:

    elsif working_value.present?
          return (working_value || 0.0) * heritable_rental_price_percentage / 100
    

    If working_value.present? working_value can not be nil so the || 0.0 never operates.

    And if it did, zero times anything, divided by anything, is still zero.

    So

    def heritable_rental_price
      return rental_price if rental_price.present?
      return 0 unless working_value.present?  
      working_value * heritable_rental_price_percentage / 100
    end
    

    However, I think the main problem is that you are assuming 0.present? returns false, when in fact it returns true. I think the check you want is unless product.heritable_rental_price.nil?

    Also should return rental_price if rental_price.present? be return rental_price unless rental_price.nil? (if rental_price defaults to zero)