Rake 任务中的事务

发布于 2024-10-18 08:50:10 字数 1236 浏览 1 评论 0原文

我正在尝试创建一个具有事务支持的 rake 任务。 User->Profile 和 User->Location 之间存在 has_one 关系。

以下代码应该会失败,因为已经有一个用户名为“foo”的用户:

ActiveRecord::Base.transaction do

  begin

    u = User.create!(:username => 'foo', :email_address => '[email protected]')

    p = Profile.create!(:first_name => 'foo', :last_name => 'bar')
    u.profile=p

    l = Location.create!(:address => "chanhassen,MN")
    u.location=l

  rescue Exception => e
    rollback()
    puts "error: #{e}"
  end

end # transaction

不幸的是,不会引发错误消息(关于重复条目),并且会创建配置文件和位置模型,但不会分配给用户。我不明白什么?

--edit--

我使用了 create!() 方法而不是 create() 方法。这成功地引发了重复用户名错误。但是,如果用户验证通过,但配置文件验证失败(例如缺少last_name 字段),则仍会在数据库中创建用户。这应该会导致事务失败(确实如此)并回滚用户(不会)。

另一个问题: User.create 不会生成 id:

#<User id: nil, username: "foo">

而 Profile.create 和 Location.create 会生成:

#<Location id: 1, locatable_id: nil, locatable_type: nil>
#<Profile id: 1, user_id: nil, first_name: "foo", last_name: "bar">

似乎所有三个模型都应该等待创建主键,直到所有验证都成功。这与 has_one 关系有关吗?

I am trying to create a rake task with transaction support. There is a has_one relationship between User->Profile and User->Location.

The following code should fail, as there is already a User with the username of 'foo':

ActiveRecord::Base.transaction do

  begin

    u = User.create!(:username => 'foo', :email_address => '[email protected]')

    p = Profile.create!(:first_name => 'foo', :last_name => 'bar')
    u.profile=p

    l = Location.create!(:address => "chanhassen,MN")
    u.location=l

  rescue Exception => e
    rollback()
    puts "error: #{e}"
  end

end # transaction

Unfortunately, the error message (about the duplicate entry) isn't raised, and the Profile and Location models are created, but not assigned to the User. What am I not understanding?

--edit--

I used the create!() method instead of the create() method. This succeeds in raising the duplicate username error. However, if the User validation passes, but the Profile validation fails (e.g. the last_name field is missing), the User is still created in the DB. This should cause the transaction to fail (it does) and rollback the User (it doesn't).

Another question: the User.create doesn't generate an id:

#<User id: nil, username: "foo">

while the Profile.create and Location.create do:

#<Location id: 1, locatable_id: nil, locatable_type: nil>
#<Profile id: 1, user_id: nil, first_name: "foo", last_name: "bar">

Seems like all three models should wait to create their primary key until all of the validations have succeeded. Is this related to the has_one relationship?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

尸血腥色 2024-10-25 08:50:10

尝试使用 create! 方法而不是 create (如 User.create! :username => 'foo')。 create 不会在错误时引发异常,create! 会引发异常。

Try using create! method instead of create (as in User.create! :username => 'foo'). create doesn't raise an exception on error, create! does that.

痞味浪人 2024-10-25 08:50:10

这具有所需的行为:

ActiveRecord::Base.transaction do
  begin

    u = User.new(:username => 'foo', :email_address => '[email protected]')

    l = Location.new(:address => "Chanhassen, MN")
    u.location=l

    p = Profile.new(:first_name => 'Foo', :last_name => 'Bar')
    u.profile=p

    u.save!

  rescue Exception => e
    ActiveRecord::Rollback
    puts e

  end
end # transaction

new() 方法不会(看起来)触发验证。 save!() 方法可以。

This has the desired behavior:

ActiveRecord::Base.transaction do
  begin

    u = User.new(:username => 'foo', :email_address => '[email protected]')

    l = Location.new(:address => "Chanhassen, MN")
    u.location=l

    p = Profile.new(:first_name => 'Foo', :last_name => 'Bar')
    u.profile=p

    u.save!

  rescue Exception => e
    ActiveRecord::Rollback
    puts e

  end
end # transaction

The new() method doesn't (it seems) trigger validation. The save!() method does.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文