在Rails中,更新记录或创建新记录(如果不存在)的最佳方法是什么? [英] In Rails, what is the best way to update a record or create a new one if it doesn't exist?
问题描述
我为某些模型创建了一条create语句,但是无论该记录是否已存在,它都会在联接表中创建一条记录。
I have a create statement for some models, but it’s creating a record within a join table regardless of whether the record already exists.
这是我的代码的外观像这样:
Here is what my code looks like:
@user = User.find(current_user)
@event = Event.find(params[:id])
for interest in @event.interests
@user.choices.create(:interest => interest, :score => 4)
end
问题是无论如何它都会创建记录。我希望仅在不存在任何记录的情况下创建记录;如果确实存在一条记录,我希望它采用找到的记录的属性并添加或减去1。
The problem is that it creates records no matter what. I would like it to create a record only if no record already exists; if a record does exist, I would like it to take the attribute of the found record and add or subtract 1.
我一直在寻找的东西称为 find_or_create_by
。找到记录后该怎么办?我希望它采用当前的:score
属性并添加1。
I’ve been looking around have seen something called find_or_create_by
. What does this do when it finds a record? I would like it to take the current :score
attribute and add 1.
是否可以找到或创建通过 id
?我不确定要找到什么属性,因为我要查看的模型是一个联接模型,该联接模型仅具有 id
外键和score属性。
Is it possible to find or create by id
? I’m not sure what attribute I would find by, since the model I’m looking at is a join model which only has id
foreign keys and the score attribute.
我尝试了
@user.choices.find_or_create_by_user(:user => @user.id, :interest => interest, :score => 4)
但是
未定义的方法
find_by_user
我该怎么办?
推荐答案
假设选择
模型具有 user_id
(与用户关联)和 interest_id
(与兴趣相关联),类似这样的方法应该可以解决问题:
Assuming that the Choice
model has a user_id
(to associate with a user) and an interest_id
(to associate with an interest), something like this should do the trick:
@user = User.find(current_user)
@event = Event.find(params[:id])
@event.interests.each do |interest|
choice = @user.choices.find_or_initialize_by_interest_id(interest.id) do |c|
c.score = 0 # Or whatever you want the initial value to be - 1
end
choice.score += 1
choice.save!
end
一些注意事项:
- 您无需在
find_or _ * _ by _ *
user_id 列>,因为您已经指示Rails仅获取属于@user
的选择
。 - 我正在使用
find_or_initialize_by _ *
,与find_or_create_by _ *
基本上相同,主要区别在于初始化
实际上并未创建记录。这与Model.new
相似,而不是Model.create
。 - 设置
c.score = 0
的块仅在记录不存在的情况下才执行。 -
choice.score + = 1
会更新记录的得分值,无论它是否存在。因此,默认分数c.score = 0
应该是初始值减去一。 - 最后,
choice.save!
将更新记录(如果已存在)或创建已初始化的记录(如果不存在)。
- You don't need to include the
user_id
column in thefind_or_*_by_*
, as you've already instructed Rails to only fetchchoices
belonging to@user
. - I'm using
find_or_initialize_by_*
, which is essentially the same asfind_or_create_by_*
, with the one key difference being thatinitialize
doesn't actually create the record. This would be similar toModel.new
as opposed toModel.create
. - The block that sets
c.score = 0
is only executed if the record does not exist. choice.score += 1
will update the score value for the record, regardless if it exists or not. Hence, the default scorec.score = 0
should be the initial value minus one.- Finally,
choice.save!
will either update the record (if it already existed) or create the initiated record (if it didn't).
这篇关于在Rails中,更新记录或创建新记录(如果不存在)的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!