1

(jruby-1.6.8、Rails 2.3.14を使用)

私は Ruby オブジェクトを持っておりexperiment、mysql データベースの既存の行を で更新するために使用しようとし.save!ていますがsave!valid?両方ともオブジェクトを返しtrueますが、実行後に db 行は変更されません:

>> result = experiment.save!
=> true

誰もこの問題に遭遇したことがありますか? また、開発中は問題なく動作します。本番環境で問題が発生しています。それはどうやってそれを壊すことができますか?行が によって更新されなかったことを示すエラーはありませんsave!。変更される唯一のことは、行のupdated_at列が後で書き込まれることです。

オブジェクトの属性を個別に取得し、UPDATEそれらを使用して SQL を実行するコードを後で追加しました。save!これは機能しますが、問題の根本に到達したいと思います。

sql = "UPDATE experiment SET attr1 = #{experiment.attr1}, attr2 = #{experiment.attr2} WHERE experimentID = #{experiment.experimentID}"
Experiment.connection.execute(sql)

実験オブジェクトは次のようになります。

>> puts "#{experiment.inspect}"
=> #<Experiment experimentID: 177, attr1: 13, attr2: 13, attr3: nil ... >

SELECT実行前のデータベース行の出力save!:

>> test_sql = "SELECT * FROM experiment WHERE experimentID = #{experiment.experimentID}"
>> sql_hash = Experiment.connection.execute(test_sql)[0]
>> puts "before save: SQL_TEXT: #{sql_hash.inspect}"
=> before save: SQL_TEXT: {"experimentID"=>177, "attr1"=>0, "attr2"=>0, "attr3"=>"", ... }

次に、experiment.save!attr1 と attr2 を 13 に更新する必要があります。ただし、それらはまだ 0 です。

該当するクラス宣言の一部を次に示します。

class Experiment < ActiveRecord::Base
  set_table_name :experiment
  set_primary_key :experimentID
  validates_presence_of :attr1, :attr2
  ...
end

編集:コメンターの提案に従って、本番ロガーレベルをデバッグに設定し、クエリされている実際のSQLを調べてみましたexperiment.save!:

Experiment Update (0.0ms)   UPDATE `experiment` SET `updated_at` = '2013-09-02 19:56:11' WHERE `experimentID` = 178

どの属性も更新しないsave!ことを選択するのはなぜですか???

他に提供できる詳細があれば教えてください。

4

1 に答える 1

2

Active Record はどの列が変更されたかを追跡し、これらのみをデータベースに保存します。この変更の追跡は、すべてを知っているわけではありません。たとえば、

user.name.gsub!(...)

Rails 4.2 より前のバージョンでは、変更として検出されませんでした。

これには 2 つの方法があります。1 つは、Active Record オブジェクトの属性を変更しないことです。これができない場合は、Active Record に何を行ったかを伝える必要があります。たとえば、

user.name.gsub!(...)
user.name_will_change!

name 属性が変更されたことを Active Record に知らせます。

于 2013-09-05T12:35:57.730 に答える