简体   繁体   中英

Rails4: NoMethodError / undefined method `*' for nil:NilClass

In my sale.rb model I want to check if the form submits a value for the column "price". If "price" is nil (as it should be if there is nothing submitted through the form) it should take the value from another table. But whenever I try to submit the form I get a NoMethodError in SalesController#create error and this line get's highlighted:

write_attribute(:price, price * quantity.to_f) unless destroyed?

Here is my code:

class Sale < ActiveRecord::Base
 before_create :price

  def price
    if price = nil
      mrr = Warehouse.where(:product => self.product).pluck(:mrr).shift.strip.sub(',', '.').to_f
      write_attribute(:price, mrr * quantity.to_f) unless destroyed?
    else
      write_attribute(:price, price * quantity.to_f) unless destroyed?
    end
  end
end

Thanks in advance!

Your check wether price is nil is wrong. You should either use

if price == nil

or

if price.nil?

Some random tips: 1. Avoid nil checks. Rails ActiveSupport library monkey-patches objects with that neat present? method, which provides more meaningful way of making sure that your objects are not blank in broad meaning of this term. For example, HTML forms don't have any special representation for null references ( nil 's), and are likely to submit empty strings '' instead.

  1. Take some time to learn basic (non-Rails) Ruby. You should understand distinction between "readers" and "writers".

  2. mrr = Warehouse.where(:product => self.product).pluck(:mrr).shift.strip.sub(',', '.').to_f - how many seconds would you or any other developer waste trying to figure out what the hell is going on here? What is mrr ? Why would you shift.strip.sub it? I have a feeling your db schema might be wrong here. If it's item cost, store it in decimal column. Which leads to my next point...

  3. NEVER EVER STORE PRICES AS FLOATS. Floating-point numbers are subject to rounding errors, since some fractions could require infinite number of digits to be expressed without rounding, and computers are not handling infinite number of anything very well, naturally. And decimal floating-point numbers in binary-based computers could be even trickier. Now, small rounding errors tend to accumulate. One hundredth of cent eventually becomes a cent, cents accumulate to dollars, and over one year in large-scale production app this could amount to some non-neglectable sum, and your company's accounting department will make your life miserable when it's time to report to your country's tax authority.

     def price=(value) value = mrr_from_warehouse if value.blank? # mrr_from_warehouse is your long query extracted to separate instance method super(value * quantity.to_f) # I doubt destroyed? method makes sense here end 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM