【问题标题】:How can I update a boolean attribute for all models given a list of ids?如何在给定 id 列表的情况下更新所有模型的布尔属性?
【发布时间】:2013-01-15 05:54:29
【问题描述】:

我正在做类似于这些 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

任何改进的想法将不胜感激。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 rails-activerecord


    【解决方案1】:

    为什么不直接做以下事情:

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

    它会更快,而且非常简单明了。

    【讨论】:

    • 谢谢。这绝对是代码方面的改进。我认为你是对的,它也会更快,因为它不需要两次进行相同的搜索。但是,我有点担心它会更新大多数模型两次。
    【解决方案2】:

    我终于明白了。

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

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

    关于这个的一个奇怪的警告是它弄乱了我的一些规格。我正在检查错误,但它给出了零。在数据库中,它似乎设置为 false。我将我的规范从 be(false) 更改为 be_false,现在感觉很安全。

    【讨论】:

    • 我不建议自己编写 sql。然后您将被绑定到特定的 DB 类型,尽管许多具有相同的语法。
    【解决方案3】:

    你可以这样做:

    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
    

    因为它是一个事务,它会很快。另请注意我如何使用“查找”,而不是“在哪里”。在我看来它更好。使代码更简洁。

    注意:我会质疑为什么您每次都需要更新每本书实体。一本一本地跟踪出版的书籍不是更聪明吗?如果每次要更新一本书时都需要传递每个书的 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
    

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

    【讨论】:

    • 将其包装在事务中是一个很好的观点。关于findwhere 虽然我同意find 会更漂亮,但它不起作用。 find 将执行查询(留下Array),而where 将其保留为ActiveRecord::Relation。我刚试了一下,它报错了,因为Array 没有响应update_all
    • 哦.. 我不知道 find 会获取数据。找一些人说,如果你做“Book.scoped.find(whatever)”,那么它会很懒。没有测试过。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 1970-01-01
    • 2011-03-01
    • 2022-01-12
    • 1970-01-01
    • 2018-03-06
    相关资源
    最近更新 更多