Ruby-on-rails 如果记录不存在则创建
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21718351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create if record does not exist
提问by gsueagle2008
I have 3 models in my rails app
我的 Rails 应用中有 3 个模型
class Contact < ActiveRecord::Base
belongs_to :survey, counter_cache: :contact_count
belongs_to :voter
has_many :contact_attempts
end
class Survey < ActiveRecord::Base
has_many :questions
has_many :contacts
end
class Voter < ActiveRecord::Base
has_many :contacts
end
the Contact consists of the voter_id and a survey_id. The Logic of my app is that a there can only be one contact for a voter in any given survey.
Contact 由voter_id 和survey_id 组成。我的应用程序的逻辑是,在任何给定的调查中,选民只能有一个联系人。
right now I am using the following code to enforce this logic. I query the contacts table for records matching the given voter_id and survey_id. if does not exist then it is created. otherwise it does nothing.
现在我正在使用以下代码来强制执行此逻辑。我在联系人表中查询与给定的voter_id 和survey_id 匹配的记录。如果不存在,则创建它。否则它什么都不做。
if !Contact.exists?(:survey_id => survey, :voter_id => voter)
c = Contact.new
c.survey_id = survey
c.voter_id = voter
c.save
end
Obviously this requires a select and a insert query to create 1 potential contact. When I am adding potentially thousands of contacts at once.
显然,这需要一个选择和一个插入查询来创建 1 个潜在的联系人。当我一次添加潜在的数千个联系人时。
Right now I'm using Resque to allow this run in the background and away from the ui thread. What can I do to speed this up, and make it more efficient?
现在我正在使用 Resque 来允许它在后台运行并远离 ui 线程。我该怎么做才能加快速度并使其更有效率?
采纳答案by Nicolas Garnil
You should add first a database index to force this condition at the lowest level as possible:
您应该首先添加一个数据库索引以在尽可能低的级别强制此条件:
add_index :contacts, [:voter_id, :survey_id], unique: true
Then you should add an uniqueness validation at an ActiveRecord level:
然后您应该在 ActiveRecord 级别添加唯一性验证:
validates_uniqueness_of :voter_id, scope: [:survey_id]
Then contact.savewill return falseif a contact exists for a specified voter and survey.
然后contact.save将返回false如果联系人存在指定的投票和调查。
UPDATE: If you create the index, then the uniqueness validation will run pretty fast.
更新:如果您创建索引,那么唯一性验证将运行得非常快。
回答by bazinga012
You can do the following:
您可以执行以下操作:
Contact.where(survey_id: survey,voter_id: voter).first_or_create
回答by cassioscabral
See if those links can help you.
看看这些链接是否可以帮助您。
Those links are for rails 4.0.2, but you can change in the api docks
这些链接适用于 rails 4.0.2,但您可以在 api 码头中更改
From the apidock: first_or_create, find_or_create_by
From the Rails Guide: find-or-create-by
来自 apidock:first_or_create,find_or_create_by
来自 Rails 指南:find-or-create-by
回答by Siva
It would be better if you let MySQL to handle it.
如果你让 MySQL 来处理它会更好。
Create a migration and add a composite unique keyto survey_id, voter_id
创建迁移并将复合唯一键添加到survey_id, voter_id
add_index :contact, [:survey_id, :voter_id], :unique=> true
Now
现在
Contact.create(:survey_id=>survey, :voter_id=>voter_id)
Will create new record only if there is no duplicates.
仅当没有重复项时才会创建新记录。

