我正在做类似于这些railscast剧集的事情:
http://railscasts.com/episodes/165-edit-multiple
http://railscasts.com/episodes/52-update-through-checkboxes
问题是那些只是试图修改所选模型。我需要更新每一个模型。
我发现的第一件事是id not in ()
并没有像我预期的那样回馈所有内容,所以我不得不为空列表做一个特例。
此代码有效,但看起来并不干净。至少我应该能够将正常情况合并为一行。
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
任何改进的想法都将受到赞赏。
答案 0 :(得分:2)
为什么不执行以下操作:
def update_published
Book.update_all(published: false)
Book.where(id: params[:book_ids]).update_all(published: true)
redirect_to books_path
end
它会更快,而且非常直接和干净。
答案 1 :(得分:0)
我终于明白了。
def update_published
Book.update_all(["published = id in (?)", params[:book_ids]])
redirect_to books_path
end
我昨天试图做类似的事情,但它仍然给我一个错误,其中?
没有填写,而且它在我的ID上做where
。今天,我终于意识到我需要将两个参数都包装成一个数组。
关于这一点的一个奇怪的警告是它搞砸了我的一些规格。我正在检查是否错误,但是它给了零。在数据库中,它似乎设置为false。我将规范从be(false)
更改为be_false
,现在感觉很安全。
答案 2 :(得分:0)
你可以这样做:
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
每当你能(许多人同意)应该遵循“瘦瘦的控制器,胖模型”的方法。这意味着您基本上将尽可能多的代码放在模型类中,而不是在任何其他地方放置它。