Tay*_*mon 4 activerecord ruby-on-rails has-many object-persistence
我正在使用Rails 1.2.3(是的,我知道)并且对于如何has_many在对象持久性方面的工作感到困惑.
为了举例,我将使用它作为我的声明:
class User < ActiveRecord::Base
has_many :assignments
end
class Assignment < ActiveRecord::Base
belongs_to :user
end
Run Code Online (Sandbox Code Playgroud)
据我了解,这会生成一个方法User#assignments.build,该方法创建一个Assignment对象,该对象user_id是接收实例id(并且其他字段在参数中指定),但不会将此对象保存在数据库中.稍后可以通过调用保存该对象Assignment#save!.
然而,我一直用作教程和参考的实用程序员使用Rails的Agile Web开发第二版说:
如果父对象存在于数据库中,则将子对象添加到集合会自动保存该子对象.
这里似乎有矛盾.我想知道的是:
some_user.assignments.build,Assignment对象是否已保存?some_user.assignments << Assignment.new,Assignment对象是否已保存?some_user.assignments << Assignment.create,是两个数据库调用,还是只有一个?如果我Assignment在创建它并将其添加到之间修改对象怎么样some_user.assignments?save!的Assignment对象User尚未保存在数据库中,会发生什么?PS我不仅仅User#assignments.create用于所有事情的原因是因为它不允许我将初始化转移到外部方法,我希望能够做到这一点.我也不想多次去数据库.
jst*_*ong 18
注意:下面的所有控制台测试都在Rails 3中运行.您可能会在Rails 1中获得不同的输出,您必须自己运行测试才能进行比较.
如果您想了解使用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)
Run Code Online (Sandbox Code Playgroud)
如您所见,两者都是在保存新用户的同时保存的.现在让我们尝试场景二:
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>
Run Code Online (Sandbox Code Playgroud)
因此,我们可以得出结论:
如果我执行some_user.assignments.build,是否保存了Assignment对象?
不
如果我执行some_user.assignments << Assignment.new,是否保存了Assignment对象?
不.这正是assignments.build所做的,没有区别.
如果我做some_user.assignments << Assignment.create,是两个数据库调用,还是只有一个?
只是作业.
如果我在创建它之间修改Assignment对象并将其添加到some_user.assignments呢?
不明白,抱歉.
如果我保存会怎么样!一个Assignment对象,其相应的User尚未保存在数据库中?
它在没有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
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.