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

时间:2011-01-06 23:44:38

标签: ruby-on-rails conditional-statements

我有一些模型的创建语句,但它在连接表中创建一条记录,无论该记录是否已存在。

以下是我的代码:

@user = User.find(current_user)
@event = Event.find(params[:id])
for interest in @event.interests
 @user.choices.create(:interest => interest, :score => 4)
end

问题是无论如何都会创建记录。我希望只有在没有记录的情况下才创建记录;如果记录确实存在,我希望它采用找到的记录的属性并加1或减1。

我一直在寻找能看到find_or_create_by的东西。当它找到记录时这会做什么?我希望它采用当前的:score属性并添加1。

是否可以通过id查找或创建?我不确定我会找到什么属性,因为我正在查看的模型是一个只有id个外键和得分属性的连接模型。

我试过

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

但得到了

  

未定义的方法find_by_user

我该怎么办?

6 个答案:

答案 0 :(得分:60)

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
})

答案 1 :(得分:23)

假设Choice模型有user_id(与用户关联)和interest_id(与兴趣相关联),这样的事情应该可以解决问题:< / p>

@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

一些注意事项:

  1. 您不需要在user_id中添加find_or_*_by_*列,因为您已经指示Rails仅提取属于choices的{​​{1}}。
  2. 我正在使用@user,这与find_or_initialize_by_*基本相同,其中一个关键区别是find_or_create_by_*实际上并未创建记录。这与initialize相似,而不是Model.new
  3. 仅当记录时,才会执行设置Model.create的块。
  4. c.score = 0将更新记录的分数值,无论其是否存在。因此,默认分数choice.score += 1应为初始值减一。
  5. 最后,c.score = 0将更新记录(如果已存在)或创建已启动的记录(如果没有)。

答案 2 :(得分:7)

find_or_create_by_user_id听起来更好

答案 3 :(得分:3)

此外,在 Rails 3 中,你可以这样做:

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

答案 4 :(得分:0)

如果您正在使用rails 4,我认为它不会像以前那样创建finder方法,因此不会为您创建find_or_create_by_user。相反,你会这样做:

@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

答案 5 :(得分:0)

在Rails 4中 您可以使用find_or_create_by来获取一个对象(如果不存在,它将创建),然后使用update来保存或更新记录,如果更新方法不存在,则更新方法将保留记录,否则更新记录。

例如

@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))