Search code examples
jqueryruby-on-railsvalidationnumber-formattingvirtual-attribute

Rails 3 - Validating against virtual attribute results in Exception


I have a virtual attribute, called currentBalance, in one of my models. An ajax call in my view populates this attribute. In the model I'm trying to validate that the net_weight is less than or equal to the currentBalance which represents total net weight for a product in inventory.

The problem is appears to be that net_weight is a float and the currentBalance attribute comes back as a string resulting in an exception that says:

comparison of Float with String failed

Here is the jquery that populates the currentBalance input field when a product is selected:

$( ".fields" ).each( function(){    
    <% @currentBals.each do |c| %>
        if( $(this).find("option:selected").text() == '<%= c.material %>' ) {   
            $(this).find("input:text[readonly]").val("<%= number_with_delimiter(c.currentBal) %>")  
        } else {
            if ($(this).find("option:selected").text() == 'Select Material'){
                $(this).find("input:text[readonly]").val("<%=  number_with_delimiter(0) %>")
            }
        }
    <% end %>    

});

and here is the validation code in the model:

validates :net_weight, presence: true, numericality: { greater_than: 0.0, less_than_or_equal_to: :currentBalance }

I think that the number_with_delimiter formatting statement is causing the problem. But I want the value to be formatted in the view.

How can I change the validation or convert the currentBalance attribute to be a float prior to the validation running?


Solution

  • So I found a solution, although I think its a bit hacky. In my controllers' create action I looped through each detail record and parsed the comma out of currentBalance attribute and then called .to_f on it.

    @shipment.details.each do |d|
             d.currentBalance = d.currentBalance.delete(',').to_f
    end
    

    I'd prefer to push this logic into the model but after multiple attempts (and in the interest of time) this approach worked. If anyone has an idea about how I can push the logic into the detail model and still make sure it validates correctly I'd be happy to try it.