如果我假设模型:
class User < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
end
当我试图运行User.first.posts.create [attributes]
,模型被创建,但它的id是nil,不保存在数据库中。有人能解释一下原因吗?我认为这种行为应该出现在#new中,而不是#create中。
你的期望是错误的。
如果验证通过,创建一个对象(或多个对象)并将其保存到数据库。无论对象是否成功保存到数据库,都会返回结果对象。
实现实际上非常简单:
def create(attributes = nil, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| create(attr, &block) }
else
object = new(attributes, &block)
object.save
object
end
end
例如,当你这样做时:
post = Post.create(title: 'Not a valid post')
这将始终返回post的实例。如果你检查对象,你会发现它没有被持久化,errors
对象会告诉你原因:
post.valid? # false
post.persisted? # false
post.errors.full_messages # ["User can't be blank."]
如果你创建了一个关联的记录,你也在改变它:
user = User.first
post = user.posts.create(attributes)
user.posts.to_a.include?(post) # true
这似乎是不希望看到的行为,但这是嵌套属性正常工作所必需的。
使用create!
(如果记录无效则会引发错误)而不是在非交互式上下文中(如种子文件),其中创建记录不应该失败。不要在无效输入不是异常事件的情况下使用它,它只是一种拐杖,类似于抛出一堆日志或在代码中放置语句。编写覆盖无效和有效输入的测试。
如果你真的需要使用一个调试器,如byebug
或pry
进入控制器的动作和检查模型实例。