如何为给定id列表的所有模型更新布尔属性?



我正在做类似于这些railscast剧集的事情:

http://railscasts.com/episodes/165-edit-multiple

http://railscasts.com/episodes/52-update-through-checkboxes

问题是那些只是试图修改选定的模型。我需要更新每一个模型。

我发现的第一件事是id not in ()没有像我期望的那样返回所有东西,所以我必须为空列表做一个特殊的情况。

这段代码可以工作,但是它看起来不是很DRY。至少我应该能够将正常情况合并到一行中。

def update_published
  if params[:book_ids].empty?
    Book.update_all(published: false)
  else
    Book.where(id: params[:book_ids]).update_all(published: true)
    Book.where("id not in (?)", params[:book_ids]).update_all(published: false)
  end
  redirect_to books_path
end

为什么不这样做呢?

def update_published
  Book.update_all(published: false)
  Book.where(id: params[:book_ids]).update_all(published: true)
  redirect_to books_path
end

它会更快,而且非常直接和干净。

我终于想通了。

def update_published
  Book.update_all(["published = id in (?)", params[:book_ids]])
  redirect_to books_path
end

我昨天试图做类似的事情,但它一直给我一个错误,其中?没有填写,它正在做我的id上的where。今天,我终于意识到我需要将这两个参数包装到一个数组中。

一个奇怪的警告是,它搞砸了我的一些规格。我检查是否为假,但结果是nil。在数据库中,它似乎被设置为false。我把我的规格从be(false)改为be_false,现在感觉很安全了。

你可以这样做:

def update_published
    Book.transaction do
      Book.update_all(published: false)
      Book.scoped.find(params[:book_ids]).update_all(published: true) #Should be Lazyloaded. Testing Now
    end
end

因为它是一个事务,所以它会非常快。还要注意我是如何使用"find",而不是"where"。在我看来,它更好。使代码更简洁。

注意:我想问为什么你每次都需要更新每一个单独的图书实体。把出版的书一本一本地记录下来不是更明智吗?如果每次要更新一本书时都需要传递每个图书ID,那么必然会遇到麻烦。这个解决方案的可扩展性不强。

你应该这样做:

def publish_book(book)
  book.published = true;
  book.save!
end

或者更好:

#Book.rb
def publish
  self.published = true
  self.save #not 100% sure you need this. Anyone?
end

只要你可以,你(许多人同意)应该遵循"瘦控制器,胖模型"的方法。这意味着您基本上将尽可能多的代码放在模型类中,而不是在任何您可以节省它的地方。

相关内容

  • 没有找到相关文章

最新更新