在其块内更新新创建的对象的关联

时间:2018-09-30 06:46:39

标签: ruby-on-rails ruby

轨5.2.1

在我的用户模型中,我有:

has_one :profile
before_create :build_profile

这在用户在我的网站上注册并创建关联的Profile对象时有效。

在内部使用seeds.rd:

require 'faker'

User.create(email: Faker::Internet.email, password: 'nopassword') do |u|
  u.profile.update_attributes({...})
  # u.create_profile({...}) ActiveRecord::RecordNotSaved: You cannot call create unless the parent is saved
end
  

NoMethodError:nil:NilClass的未定义方法update_attributes

是否在seed.rb中未调用ActiveRecord?什么有效?:

[...]

u.build_profile({...})

[...]

现在的问题是,由于before_create :build_profile,我有重复的对象。从user.rb文件中删除此行,一切正常。我不需要删除它,仍然可以毫无问题地运行我的seed.rb。如何实现呢?

2 个答案:

答案 0 :(得分:1)

如果创建用户后更新配置文件该怎么办?

u = User.create(...)
u.profile.update_attributes({...})

如果您查看要创建的source code,您会看到在执行该块之后调用了save,因此您的before_create方法直到该块执行后才会被调用。

>

如果您在块内调用profile.update_attributes,它将在before_create运行之前创建一个配置文件,然后before_create将创建另一个配置文件。

如果您真的想使用该块,则可以在before_create方法中进行检查,该方法仅在不存在配置文件的情况下才会创建该配置文件:

before_create :ensure_profile_built

private
def ensure_profile_built
  build_profile unless profile
end

答案 1 :(得分:0)

这是因为在保存对象之前调用了create块。这意味着在执行块时尚未触发回调,您可以使用以下命令轻松检查它:

User.create { |u| puts u.persisted? }

为了使它适合您使用,您可以使用tap:

User.create.tap { |u| u.profile.update_attributes }