控制器批量更新的最佳实践

Chr*_*det 21 ruby rest model-view-controller ruby-on-rails-3

我想知道在控制器中允许批量编辑/更新的最佳做法是什么.我真的找不到关于这个主题的文章或指南.

Rob*_*ead 40

我看到你用REST标记了你的问题.

要以REST形式执行此操作,您需要考虑集合或更新本身作为资源.

假设您正在使用Product对象.

您可以将PUT转换为/ product_batches/[某个标识符],这将调用ProductBatchesController #update,但是您会被困在[某些标识符]中.您可以使ProductBatch成为单一资源,然后您就不需要id.

更好的方法是POST到/ product_bulk_updates,这将调用ProductBulkUpdatesController #create

class ProductBulkUpdatesController < ApplicationController

  def create
    # your magic here
    # - update_all if you are making the same change to all Products
    # - looping through the hashes in params[products] if you are passing in distinct changes to each.
  end

end
Run Code Online (Sandbox Code Playgroud)

这是另一个线程: 通过REST(RESTful)API进行批量收集操作

  • 我礼貌地不同意.将操作定义为资源并不是一种非常RESTful的方法.你要做的是更新一个已经由`/ products`定义的集合资源(坚持这个例子).所以`PUT | PATCH/products`似乎更合适(取决于它是否应该是幂等的).拥有表示操作的资源(如示例中的Update)会与REST方法冲突.此外,它建议您可以创建,删除和更新"更新". (2认同)

tok*_*and 10

我不认为有一种标准的方式.你可以使用update_attributes(例如PostsController):

def update_bulk
  @posts = Post.where(:id => params[:ids])

  # wrap in a transaction to avoid partial updates (move this logic to the model!)
  if @posts.all? { |post| post.update_attributes(params[:post]) }
    redirect_to(posts_url)
  else
    redirect_to(:back)
  end
end
Run Code Online (Sandbox Code Playgroud)

或使用update_all,但请注意,不会调用回调或验证:

def update_bulk
  Post.where(:id => params[:ids]).update_all(params[:post])
  redirect_to(posts_url)
end
Run Code Online (Sandbox Code Playgroud)


cod*_*joe 6

如果你有幸在Rails 3中工作,那么你应该确保在Rails 2中查看ActiveRecord :: Relation#update_all或ActiveRecord :: Base#update_all:

构建单个SQL更新语句比完整SQL往返更新元素要好得多.

重要说明:这确实是使用SQL更新语句的批量更新.它不会实例化任何ActiveRecord对象,因为更新仅在SQL中执行.因此,不会调用ActiveRecord回调和验证.

上面的URL中的示例:

# Update all customers with the given attributes
Customer.update_all :wants_email => true

# Conditions from the current relation also works
Book.where('title LIKE ?', '%Rails%').update_all(:author => 'David')
Run Code Online (Sandbox Code Playgroud)

注意:据我所知,从互联网上的帖子来看,这个功能介于Rails 3.0.3,3.0.7-3.0.9之间.

直到3.1.0我才发现这个功能,所以我无法证实.