4

Rails 1.2.3を使用しています(ええ、私は知っています)が、has_manyオブジェクトの永続性に関してどのように機能するかについて混乱しています。

例として、これを宣言として使用します。

class User < ActiveRecord::Base
    has_many :assignments
end

class Assignment < ActiveRecord::Base
    belongs_to :user
end

私が理解しているように、これは、とりわけ、受信インスタンスのオブジェクト(および引数で指定された他のフィールド)User#assignments.buildを作成するメソッドを生成しますが、このオブジェクトをデータベースに保存しません。オブジェクトは、を呼び出すことで後で保存できます。Assignmentuser_ididAssignment#save!

ただし、チュートリアルおよびリファレンスとして使用している、Railsを使用した実用的なプログラマーのアジャイルWeb開発、第2版は、次のように述べています。

親オブジェクトがデータベースに存在する場合、子オブジェクトをコレクションに追加すると、その子が自動的に保存されます。

ここには矛盾があるようです。私が知りたいのは:

  • そうした場合some_user.assignments.buildAssignmentオブジェクトは保存されますか?
  • そうした場合some_user.assignments << Assignment.newAssignmentオブジェクトは保存されますか?
  • 私がそうする場合some_user.assignments << Assignment.create、2つのデータベース呼び出しが行われますか、それとも1つだけですか?Assignmentオブジェクトを作成してから追加するまでの間にオブジェクトを変更するとどうなりsome_user.assignmentsますか?
  • save!対応するAssignmentオブジェクトがUserまだデータベースに保存されていない場合はどうなりますか?

PS私がUser#assignments.createすべてに使用しない理由は、初期化を外部メソッドにファームアウトできないためです。これは、私が実行できるようにしたいことです。また、データベースに何度もアクセスしたくありません。

4

1 に答える 1

19

注:以下のすべてのコンソールテストはRails 3で実行されます。Rails1では異なる出力が得られる場合があり、比較するには自分でテストを実行する必要があります。

Active Recordの舞台裏で何が起こっているのかを理解したい場合は、Railsコンソールを手元に置いておくことは非常に価値があります。保存されていないオブジェクトで何が起こるかを次に示します。

u = User.new
#<User id: nil, name: nil, created_at: nil, updated_at: nil> 

u.assignments.build(:name => "example")
#<Assignment id: nil, name: "example", user_id: nil, created_at: nil, updated_at: nil>

u.save
#SQL (0.2ms)  INSERT INTO `users` (`created_at`, `name`, `updated_at`) VALUES ('2012-06-01 19:25:45', NULL, '2012-06-01 19:25:45')
#SQL (0.2ms)  INSERT INTO `assignments` (`created_at`, `name`, `updated_at`, `user_id`) VALUES ('2012-06-01 19:25:45', 'example', '2012-06-01 19:25:45', 1)

ご覧のとおり、新しいユーザーが保存されたときに両方が同時に保存されます。次に、シナリオ2を試してみましょう。

u = User.create!(:name => "test")
#SQL (0.2ms)  INSERT INTO `users` (`created_at`, `name`, `updated_at`) VALUES ('2012-06-01 19:27:21', 'test', '2012-06-01 19:27:21')
#<User id: 2, name: "test", created_at: "2012-06-01 19:27:21", updated_at: "2012-06-01 19:27:21"> 

u.assignments.build(:name => "example")
#<Assignment id: nil, name: "example", user_id: 2, created_at: nil, updated_at: nil>

したがって、これから次のように結論付けることができます。

some_user.assignments.buildを実行すると、Assignmentオブジェクトは保存されますか?

いいえ

some_user.assignments << Assignment.newを実行すると、Assignmentオブジェクトは保存されますか?

いいえ。これは、assignments.buildが行うこととまったく同じであり、違いはありません。

some_user.assignments << Assignment.createを実行した場合、2つのデータベース呼び出しが行われますか、それとも1つだけですか?

ただの割り当て。

作成してからsome_user.assignmentsに追加するまでの間にAssignmentオブジェクトを変更した場合はどうなりますか?

すみません、意味分からない。

保存するとどうなりますか?対応するユーザーがまだデータベースに保存されていないAssignmentオブジェクト?

user_idなしでデータベースに保存されます。次に、ユーザーに対してsaveを呼び出すと、割り当てに対して更新コマンドが発行され、ユーザーIDが追加されます。これがコンソールにあります:

u = User.new(:name => "John Doe")
#<User id: nil, name: "John Doe", created_at: nil, updated_at: nil> 

a = Assignment.new(:name => "test")
#<Assignment id: nil, name: "test", user_id: nil, created_at: nil, updated_at: nil> 

u.assignments << a
#[#<Assignment id: nil, name: "test", user_id: nil, created_at: nil, updated_at: nil>] 

a.save!
#SQL (0.2ms)  INSERT INTO `assignments` (`created_at`, `name`, `updated_at`, `user_id`) VALUES ('2012-06-01 19:33:24', 'test', '2012-06-01 19:33:24', NULL)

a.user_id
#nil 

u.save!
#INSERT INTO `users` (`created_at`, `name`, `updated_at`) VALUES ('2012-06-01 19:33:36', 'John Doe', '2012-06-01 19:33:36')
#UPDATE `assignments` SET `user_id` = 3, `updated_at` = '2012-06-01 19:33:36' WHERE `assignments`.`id` = 3

お役に立てれば。

于 2012-06-01T19:35:29.187 に答える