1

属性更新:config.time_zone = 'Warsaw'Railsのconfig.time_zoneと日時は、私が持っている自分のアプリケーションで

私が持っている奇妙な問題、Railsは日時フィールドの比較ですで問題が発生しているように、それが思われることです。 datetimeを1時間前に変更した場合(Warsawは現在タイムゾーン+0100になっています)、フィールドが変更されてもRailsはデータベースを更新しません。しかし、フィールドをもう一度変更すると、更新はデータベースに送られます。

例:

(Railsの3.1.0、ルビー-1.9.2-P290、新鮮なレールアプリ):

$ rails g model User starts_at:datetime 
$ rake db:migrate 
$ rails c 
Loading development environment (Rails 3.1.0) 
ruby-1.9.2-p290 :001 > u = User.create({:starts_at => "2011-01-01 10:00"}) 
SQL (21.3ms) INSERT INTO "users" ("created_at", "starts_at", "updated_at") VALUES (?, ?, ?) [["created_at", Tue, 13 Dec 2011 11:32:50 CET +01:00], ["starts_at", Sat, 01 Jan 2011 10:00:00 CET +01:00], ["updated_at", Tue, 13 Dec 2011 11:32:50 CET +01:00]] 
=> #<User id: 1, starts_at: "2011-01-01 09:00:00", created_at: "2011-12-13 10:32:50", updated_at: "2011-12-13 10:32:50"> 
ruby-1.9.2-p290 :002 > u.starts_at 
=> Sat, 01 Jan 2011 10:00:00 CET +01:00 # datetime created 
ruby-1.9.2-p290 :003 > u.starts_at = "2011-01-01 09:00:00" # new datetime with one hour back 
=> "2011-01-01 09:00:00" 
ruby-1.9.2-p290 :004 > u.starts_at 
=> Sat, 01 Jan 2011 09:00:00 CET +01:00 # changed datetime 
ruby-1.9.2-p290 :005 > u.save 
=> true 
ruby-1.9.2-p290 :006 > u.starts_at = "2011-01-01 09:00:00" 
=> "2011-01-01 09:00:00" 
ruby-1.9.2-p290 :007 > u.save 
    (0.3ms) UPDATE "users" SET "starts_at" = '2011-01-01 08:00:00.000000', "updated_at" = '2011-12-13 10:33:17.919092' WHERE "users"."id" = 1 
=> true 

私が持っているので、私は、この新鮮なアプリでそれをテストしてみました大規模なアプリケーションでは、この問題。何が起こっている?私はRailsコードをブラウズしようとしましたが、関連するコードをコンソール(update、assign_attributes、さらにtime_zone_conversionをチェックしたもの)で '手書き'に再コピーしようとしましたが、実際には動作しませんでした。

+0

データベースのレコードが更新されていないことは確かですか?最初に値を保存した後に値が表示されることはありません。コンソールの5行目に示すように 'u.save'を実行した結果を表示してから' u.reload'を実行してから 'u.starts_at'を実行できますか? –

+0

文字列ではなくTimeの実際のインスタンスを使用していれば、より良い運を得られると思います。 –

+0

更新されていません。実際のTimeインスタンスと文字列によって作成される違いはありません。フォームの問題でもあるため、文字列も必要です。 – schiza

答えて

3

あなたも同様の問題に遭遇したようです。

問題がここに表示されます。 https://github.com/rails/rails/blob/3-1-stable/activerecord/lib/active_record/attribute_methods/dirty.rb#L62

すると値は、それが新しい古い&を比較して変更された場合、それはテストレール:

キャッシュから=古い(現在のタイムゾーンでの時間ですUTCで)

新しい=時間(00:00)データベース

に保存されたとして

時間の違いがUTCオフセットの場合、上記は誤って成功します(新しいキャッシュされた値は意図した変更を保持します)。

次回のセーブ/アップデートは、新しいキャッシュされた値と比較され、フィールドが変更されたものとしてマークされます。

EDIT:

は、いくつかのテストを完了、これは私のためによく働く:

https://github.com/rails/rails/blob/3-1-stable/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb#L50

変更

write_attribute(:#{attr_name}, original_time) 

Bori

write_attribute(:#{attr_name}, time.in_time_zone('UTC').to_s) 

へs

+0

それは動作していない、それはかなりではない。問題は、新しいdatetimeオブジェクトを作成するために与えられた文字列であると思います。それはUTCなので、タイムゾーンが指定されていないと間違って作成されていると仮定します。Timeオブジェクトの場合は正常に動作していますが、DateTimeオブジェクトには 'zone'設定がありません。これを管理する方法は?日付文字列はフォーム内のタイムピッカーから与えられ、更新はモデルのdatetimeフィールドにDateTimeを使用しています – schiza

+0

タイムピッカーの結果をローカルのRailのタイムゾーンに変換しないのはなぜですか? (または、モデルをTime.zoneオブジェクトに変換するためにフィルタを適用します)。 DateTimeもタイムゾーンを維持できるはずです。 – Boris

+0

しかし、/それはバグですが、Railsチームはこれについて黙っています。私はモデルやそれ以外の方法でフィルタリングしますが、アプリケーションの1か所にはありませんので、臭いになり始めます。** edit **:私はあなたの編集に気づいていませんでした;)、うまくいくはずです:) – schiza

関連する問題