简体   繁体   English

在Rails中,如果记录不存在,更新记录或创建新记录的最佳方法是什么?

[英]In Rails, what is the best way to update a record or create a new one if it doesn't exist?

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

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. 如果记录确实存在,我希望它获取找到的记录的属性并加1或减1。

I've been looking around have seen something called find_or_create_by . 我一直在四处寻找一些名为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. 我希望它采用当前:score属性并添加1。

Is it possible to find or create by id ? 是否可以通过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. 我不确定我会找到什么属性,因为我正在查看的模型是一个只有id外键和score属性的连接模型。

I tried 我试过了

@user.choices.find_or_create_by_user(:user => @user.id, :interest => interest, :score => 4)

but got 但得到了

undefined method find_by_user undefined方法find_by_user

What should I do? 我该怎么办?

my_class = ClassName.find_or_initialize_by_name(name)

my_class.update_attributes({
   :street_address => self.street_address,
   :city_name => self.city_name,
   :zip_code => self.zip_code
})

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: 假设Choice模型有一个user_id (与用户关联)和一个interest_id (与兴趣相关联),这样的事情可以做到这一点:

@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

Some notes: 一些说明:

  1. You don't need to include the user_id column in the find_or_*_by_* , as you've already instructed Rails to only fetch choices belonging to @user . 您不需要在find_or_*_by_*包含user_id列,因为您已经指示Rails仅提取属于@user choices
  2. I'm using find_or_initialize_by_* , which is essentially the same as find_or_create_by_* , with the one key difference being that initialize doesn't actually create the record. 我正在使用find_or_initialize_by_* ,它与find_or_create_by_*基本相同,其中一个关键区别是initialize实际上并不创建记录。 This would be similar to Model.new as opposed to Model.create . 这与Model.new相似,而不是Model.create
  3. The block that sets c.score = 0 is only executed if the record does not exist. 该设置块c.score = 0 ,如果记录存在时,才会执行。
  4. choice.score += 1 will update the score value for the record, regardless if it exists or not. choice.score += 1将更新记录的分数值,无论它是否存在。 Hence, the default score c.score = 0 should be the initial value minus one. 因此,默认分数c.score = 0应该是初始值减1。
  5. Finally, choice.save! 最后, choice.save! will either update the record (if it already existed) or create the initiated record (if it didn't). 将更新记录(如果已存在)或创建启动记录(如果没有)。

find_or_create_by_user_id听起来更好

此外,在Rails 3中,您可以:

@user.choices.where(:user => @user.id, :interest => interest, :score => 4).first_or_create

If you're using rails 4 I don't think it creates the finder methods like it used to, so find_or_create_by_user isn't created for you. 如果您使用的是rails 4,我认为它不会像以前那样创建finder方法,因此不会为您创建find_or_create_by_user。 Instead you'd do it like this: 相反,你会这样做:

@user = User.find(current_user)
@event = Event.find(params[:id])
for interest in @event.interests
 @user.choices.find_or_create_by(:interest => interest) do |c|
  c.score ||= 0
  c.score += 1
 end
end

In Rails 4 You can use find_or_create_by to get an object(if not exist,it will create), then use update to save or update the record, the update method will persist record if it is not exist, otherwise update record. 在Rails 4中你可以使用find_or_create_by来获取一个对象(如果不存在,它将创建),然后使用update来保存或更新记录,如果不存在则更新方法将保持记录,否则更新记录。

For example 例如

@edu = current_user.member_edu_basics.find_or_create_by(params.require(:member).permit(:school))

if @edu.update(params.require(:member).permit(:school, :majoy, :started, :ended))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Rails:检查数据库中是否存在记录的最佳方法是什么? - Rails: what is the best way to check if the record doesn't exist in the database? 更新记录(如果存在),否则创建新记录 - update record if exist else create new record rails Rails-创建记录或更新记录的最有效方法是什么(如果记录存在)? - Rails - what is the most efficient way to create record or update it (if the record exists)? 如果不存在,则使用#update方法创建新记录 - Using #update method to create new record if one does not exist Rails ActiveRecord回调:如果存在则进行更新,如果不存在则进行创建 - Rails ActiveRecord Callbacks: Update if Exists, Create if Doesn't Exist Rails-如果用户没有默认头像,最好的显示方法是什么? - Rails - What is the best way to display default avatar if user doesn't have one? 在 Rails 模型中创建“一个”到“一个或两个”关系的最佳方法是什么? - what is the best way to create "one" to "one or two" relation in rails models? 将记录加入 Rails 范围的最佳方法是什么? - What is the best way to join a record to a range in rails? Rails:当Record不存在时Record存在回滚 - Rails: Record Exists Rollback when Record doesn't exist Ruby on Rails抱怨Active Record内置的一种不存在的方法。 什么? - Ruby on Rails is complaining about a method that doesn't exist that is built into Active Record. What?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM