我正在做类似于这些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
只要你可以,你(许多人同意)应该遵循"瘦控制器,胖模型"的方法。这意味着您基本上将尽可能多的代码放在模型类中,而不是在任何您可以节省它的地方。