Reputation: 211
I have a DB Table for a Model entitled TradeDailyAverage. It has a date
(DateTime) & averageprice
(decimal) column
When I run this, I can't get the averageprice attribute to update:
newaverage = TradeDailyAverage.find_or_initialize_by_date(date)
newaverage.update_attributes :averageprice => dailyaverage
Further, when I run this, the date will show up, but the averageprice will not show up in rails console. It only shows up as blank:
newaverage = TradeDailyAverage.find_or_initialize_by_date(date)
puts newaverage.averageprice
puts newaverage.date
Is there anything special that I need to do to averageprice before I save it?
Here is all of the entire Rake Task for your reference:
averages = Trade.where('date >= ?', 7.days.ago).average(:price, :group => "DATE_TRUNC('day', date - INTERVAL '1 hour')")
# 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)
newaverage = TradeDailyAverage.find_or_initialize_by_date(date)
newaverage.update_attributes :averageprice => dailyaverage
Upvotes: 0
Views: 5070
Reputation: 211
My issue was simply that upon saving to my database, PostgreSQL was changing the hourly time, possibly due to a timezone issue. Thus, all of my instances above were new, and I couldn't update attributes of an existing model. So, I converted my datetime data to dates, changed my date db column to date instead of datetime, and now everything is working smoothly. Yves gives some great info above though which helped me later on.
Upvotes: 1
Reputation: 1996
If you want to use find_or_initialize_by
you need to think carefully about the implications. Lets take your first example:
newaverage = TradeDailyAverage.find_or_initialize_by_date(date)
newaverage.update_attributes :averageprice => dailyaverage
This should work, when the TradeDailyAverage
for the given date
is already in the database. It should not work however, when you get a new record back. The reason is simply because a new record is not persisted to the database. There is no way for update_attributes
to update a non persisted record. You have two options here:
1.) Do not use update_attributes
but assign the value and call save
. This works for both, new and created records:
newaverage = TradeDailyAverage.find_or_initialize_by_date(date)
newaverage.averageprice = dailyaverage
newaverage.save
2.) Do not use find_or_initialize_by
but find_or_create_by
. This way if the record does not exist, a new one is directly written to the database. Now update_attributes
should work because you always get persisted records back. Note that this approach has the drawback that you save records without an averageprice
to the database. I would not recommend that.
The explanation above should also explain your second example:
newaverage = TradeDailyAverage.find_or_initialize_by_date(date)
puts newaverage.averageprice
puts newaverage.date
This should output the averageprice
and the date for persisted records. If you get a newly initialized record back though, it will only display the date. Since you only initialized the record with a date object, there is no way that the averageprice
is already set.
Upvotes: 3