Model Attribute Won't Update, Validation Error Called On Separate Attribute Not Being Updated?

为君一笑 提交于 2019-12-12 03:31:11

问题


I have the following semi-advanced DB query that is going through hourly prices for the last 10 years and returning daily average prices for the last seven days:

averages = Trade.where('date >= ?', 7.days.ago).average(:price, :group => "DATE_TRUNC('day', date - INTERVAL '1 hour')")

This returns the date (for that day) and an averageprice like this:

"2012-12-29 00:00:00"=>#<BigDecimal:7f97932be328,'0.2513458333 33333333E2',27(27)>

I then loop through each response and save them as new records in a TradeDailyAverage Model.

    # Loops through each daily average produced above 
    averages.each do |date, avg|

     # Converts the BigDecimal to Floating Point(?)
     averagefloat = avg.to_f

     # Rounds the Daily Average to only two decimal points
     dailyaverage = number_with_precision(averagefloat, :precision => 2)

     # Creates a new Object in the PpDailyAverage table  
     TradeDailyAverage.create(date: date, averageprice: dailyaverage)

This works, but since this will be an hourly Rake Task, with new prices coming in every hour, how can I change this to first find a TradeDailyAverage by date and if it exists, update the averageprice attribute, or create a new record if it doesn't exist.

Validate_uniqueness is set on TradeDailyAverage Model.

Update

When I do this, 7 items appear, with accurate averages. But they just won't save. When I add newaverage.save! I get a "Validation Error: Date has already been taken!"

 newaverage = TradeDailyAverage.find_or_initialize_by_date(date: date)
          newaverage.averageprice = dailyaverage
          puts newaverage.date
          puts newaverage.averageprice

Also, if I do newaverage.new_record? Ever average returns TRUE


回答1:


I think you'd want something like this:

tda = TradeDailyAverage.first_or_initialize(date: date)
tda.averageprice = dailyaverage
tda.save



回答2:


The issue (thanks to Alex's help) was due to a difference in the datetimes. Upon saving to a PG db, the hour would change on the datetime. This may be due to a timezone issue in the db. So, the code above could not find existing records, since it contained a different hourly time than what has been saved in the database.

Since I am producing daily averages, I don't need the time, just the date in the date column. So, I converted my dates to date to avoid the time difference issue. Also I changed the code a bit with a Case, so that I can report errors. I don't think this is very efficient, but it is working for now. I believe Alex's solution above may also work as long as the datetime values are converted to dates with .to_date:

# Loops through each daily average produced above 
    averages.each do |datetime, avg|

    # Converts the BigDecimal to Floating Point(?)
    avgfloat = avg.to_f

    # Rounds the Daily Average to only two decimal points
    avgprice = number_with_precision(avgfloat, :precision => 2)

    # Converts datetime to date since this will not work with datetime (PostgreSQL is time-zoned challenged)    
    avgdate  = datetime.to_date

        # These are printed to use for testing. 
      puts avgdate
      puts avgprice

      # Starts Case to either report an error, update an existing record, or create new.
      case

        when avgdate.blank? || avgprice.blank?
            puts "Something went terribly wrong with your seven day averages producing algorithm."

        when TradeDailyAverage.exists?(:date=>avgdate)
            updateavg = TradeDailyAverage.find_by_date(avgdate)
            updateavg.averageprice = avgprice
            updateavg.save

        else
            TradeDailyAverage.create(:date=>avgdate, :averageprice=>avgprice)

        end # Ends Case  

    end # Ends Loop for each Daily Average 


来源:https://stackoverflow.com/questions/14162771/model-attribute-wont-update-validation-error-called-on-separate-attribute-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!