使用ActiveRecord的最佳方法:如果存在则删除其他创建

时间:2015-02-25 10:50:56

标签: ruby-on-rails ruby activerecord

我有这条路线为某个提示创建收藏夹:

def favorite
  @tip = Tip.find(params[:id])
  Favorite.create(user: current_user, tip: @tip)
  redirect_to :action => "show", :id => @tip.id
end

我希望它更像是一个切换。所以:如果用户对某个提示的收藏已经存在,那么它应该删除这个收藏。如果它是用户和提示的新组合,它应该使用这些值创建一个新的收藏夹。

最好和最美好的方式是什么?

7 个答案:

答案 0 :(得分:4)

试试这个,我认为它是最简洁的解决方案:

def favorite
  # Since this is about a favorite object, the main subject here 
  # is that favorite object, so you just need to deal with it
  favorite = Favorite.find_or_initialize_by(user_id: current_user.id, tip_id: params[:id])
  favorite.persisted? ? favorite.destroy : favorite.save
  # I do not know if you should redirect to this tip if 
  # the associated favorite has been deleted 
  redirect_to favorite.tip
end

答案 1 :(得分:1)

试试这个。它可能对你有用

def favorite
  @tip = Tip.find(params[:id])
  @fav=Favorite.where(user: current_user, tip: @tip)
  if @fav !=nil
     @fav.destroy
  else
      Favorite.create(user: current_user, tip: @tip)
  end

  redirect_to :action => "show", :id => @tip.id
end

答案 2 :(得分:1)

first_or_create(Link)怎么样?有了这个,你就可以解决这个问题:

def favorite
  @tip = Tip.find(params[:id])
  Favorite.where(user: current_user, tip: @tip).first_or_create
  redirect_to :action => "show", :id => @tip.id
end

这个可能很棘手,所以如果你想传递给你最喜欢的对象有任何值 - 无论是创建还是更新 - 你都可以这样做:

def favorite
  @tip = Tip.find(params[:id])
  Favorite.where(user: current_user, tip: @tip).first_or_create do |favorite|
    # favorite is the one found or the one that will be created
    favorite.rating = 5 # just an example how you can use it
  end
  redirect_to :action => "show", :id => @tip.id
end

更改将会保留,您仍然可以使用非常干净的代码(不需要任何if)。

希望有所帮助!

答案 3 :(得分:0)

窃取其他人的答案并使用find_by

def favourite
  @tip = Tip.find(params[:id])
  favourite = @tip.favourites.find_by(user_id: current_user.id)
  if favourite
    favourite.destroy
  else
    @tip.favorites << Favorite.new(user_id: current_user.id)
  end

  redirect_to action: :show, id: @tip.id
end

如果您已使用资源设置路线,则重定向将为

redirect_to @tip

答案 4 :(得分:0)

我在收藏夹模型

中创建了一个方法
def self.toggle_favorite(tip)
  return tip.favorite.destroy if tip.favorite
  tip.favorite.create(user: current_user)
end

然后在您的控制器中使用该方法

def favorite
  @tip = Tip.find(params[:id])
  Favorite.toggle_favorite(@tip)
  redirect_to :action => "show", :id => @tip.id
end

答案 5 :(得分:0)

恕我直言“复杂”的逻辑属于一个模型:

# in you Favorite model
def self.toggle(user, tip)
  fav = where(user: user, tip: tip).first
  fav.try(:destroy!) || create!(user: user, tip: tip)
end

# in your controller
def favorite
  @tip = Tip.find(params[:id])
  Favorite.toggle(current_user, @tip)

  redirect_to :action => "show", :id => @tip.id
end

答案 6 :(得分:0)

您需要检查用户是否为adding new or removing the existing,方法是将identifier传递给服务器,该服务器会检查可用的条目。例如,在这里,我检查用户是否正在添加标签或者通过喜欢或不喜欢标签来移除标签,因此将like/dislike identifier与网址一起传递然后使用它。

例如:假设用户正在添加/修改/删除自己喜欢的视频标记。

         def add_video_in_profile
            ##get all available tags
            @video_cat = VideoCategory.find_by_video_type params[:type]
              if params[:rel]=="Like"
              ##create new if not exits if like else delete selected item  
             current_user.user_video_categories.find_or_create_by_video_category_id(:video_category_id=>@video_cat.id) unless !current_user.user_video_categories.find_or_create_by_video_category_id(:video_category_id=>@video_cat.id)            
              else
             ##delete selected item if dislike              
            video_cat=current_user.user_video_categories.where(:video_category_id=>@video_cat.id)
                  video_cat.delete_all
              end    
            end