0

過去 10 年間の時間料金を調べ、過去 7 日間の毎日の平均料金を返す次の準高度な DB クエリがあります。

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

dateこれは、 (その日の)と次のaveragepriceようなものを返します。

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

次に、各応答をループして、TradeDailyAverage モデルに新しいレコードとして保存します。

    # 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)

これは機能しますが、これは 1 時間ごとのRake Taskであり、新しい価格が 1 時間ごとに入力されるため、これを変更して最初に TradeDailyAverage を見つけ、date存在する場合は属性を更新するか、存在しない場合averagepriceは新しいレコードを作成するにはどうすればよいですか?存在しません。

Validate_uniqueness は TradeDailyAverage モデルに設定されています。

アップデート

これを行うと、正確な平均で 7 つの項目が表示されます。しかし、彼らはただ保存しません。追加するnewaverage.save!と、「検証エラー: 日付は既に取得されています!」というメッセージが表示されます。

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

また、newaverage.new_record を実行すると? これまでの平均は TRUE を返します

4

2 に答える 2

2

次のようなものが欲しいと思います:

tda = TradeDailyAverage.first_or_initialize(date: date)
tda.averageprice = dailyaverage
tda.save
于 2013-01-04T18:33:05.440 に答える
0

この問題 (アレックスの助けのおかげで) は、日時の違いによるものでした。PG データベースに保存すると、日時の時間が変更されます。これは、データベースのタイムゾーンの問題が原因である可能性があります。そのため、データベースに保存されているものとは異なる時間単位が含まれていたため、上記のコードは既存のレコードを見つけることができませんでした。

私は毎日の平均を作成しているので、日付列の日付だけで時間は必要ありません。そのため、時差の問題を回避するために、日付を日付に変換しました。また、エラーを報告できるように、Case でコードを少し変更しました。これはあまり効率的ではないと思いますが、今のところ機能しています。日時の値が次の日付に変換されている限り、上記のアレックスのソリューションも機能する可能性があると思います.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 
于 2013-01-05T18:28:29.140 に答える