Rails - 如何使用查找或创建

AnA*_*ice 17 ruby ruby-on-rails ruby-on-rails-3

我有以下内容:

@permission = @group.permissions.create(
  :user_id => @user.id,
  :role_id => 2,
  :creator_id => current_user.id)
Run Code Online (Sandbox Code Playgroud)

如何更新它find_or_create,以便如果此记录已存在,则分配给@permission它,如果不存在,则创建记录?

Gav*_*ler 51

虽然接受的答案是正确的,但重要的是要注意在Rails 4中这种语法将会改变(以及散列语法).你应该写下面的内容:

@permission = Permission.where(
  user_id: @user.id, 
  role_id: 2, 
  creator_id: current_user.id).first_or_create
Run Code Online (Sandbox Code Playgroud)

这实际上看起来更接近你原来的方法!有关详细信息,请参阅" 弃用的查找器" 小节.

  • 你知道还会改变什么吗?旧的哈希语法.您可能想要更新您的答案.应该是,例如:`user_id:@ user.id`. (4认同)
  • 这将改变Ruby而不是Rails;)可能想要更新你的评论以反映这一点......除非你是负责完全从Ruby删除旧哈希火箭语法的开发人员的亲密朋友,否则我会完全撤回你的陈述.以下SO链接中的开发人员帖子解释了原因,虽然这是在2012年编写的,但它仍然有效:http://stackoverflow.com/a/10004344/1629012 (2认同)

fl0*_*00r 19

相关主题:

在Rails 3中查找_or_create_by并更新以创建记录

您可以使用自己的update_or_create方法扩展ActiveRecord (请参阅相关主题),然后您可以使用它

@permission = Permission.update_or_create_by_user_id_and_role_id_and_creator_id(@user.id, 2, current_user.id) do |p|
  p.group_id = @group.id
end
Run Code Online (Sandbox Code Playgroud)

或者您可以使用find_or_create_by...方法:

@permission = Permission.find_or_create_by_user_id_and_role_id_and_creator_id(@user.id, 2, current_user.id)
@permission.group = @group
@permission.save
Run Code Online (Sandbox Code Playgroud)

  • 因为你应该自己扩展它(查看相关主题http://stackoverflow.com/questions/5578625/find-or-create-by-in-rails-3-and-updating-for-creating-records/5580108# 5580108) (2认同)

Bla*_*son 6

我正在用版本化答案更新问题.因为它很重要.


Rails 4(docs)

有一些方法可以"找到或创建"一个对象,一个是 find_or_create_by(args)

Client.find_or_create_by(email: "bambam@flinstones.com", phone: "4255551212")
Run Code Online (Sandbox Code Playgroud)

社区首选的方式是使用where

client = Client.where(email: "bambam@flinstones.com", phone: "4255551212").first_or_create

然后你可以做类似的事情:

client = Client.where(client_params.slice(:email, :phone)).first_or_create
client.update(client_params)
Run Code Online (Sandbox Code Playgroud)

Rails 3(docs)

假设您要查找名为"Andy"的客户端,如果没有,请创建一个并另外将其locked属性设置为false.您可以通过运行:

client = Client.where(:first_name => 'Andy').first_or_create(:locked => false)
# => #<Client id: 1, first_name: "Andy", orders_count: 0, locked: false, created_at: "2011-08-30 06:09:27", updated_at: "2011-08-30 06:09:27">
Run Code Online (Sandbox Code Playgroud)