【问题标题】:How do I add a method to a Rails app which updates a collection of objects?如何向 Rails 应用程序添加更新对象集合的方法?
【发布时间】:2011-11-08 19:46:23
【问题描述】:

我在 Rails 和 Jquery Mobile 中有一个非常标准的 CRUD 应用程序,其中有两个与我的问题相关的模型:

class Wall < ActiveRecord::Base
  has_many   :problems
end

class Problem < ActiveRecord::Base
  # boolean attribute is_live
  belongs_to  :wall
end

在显示每面墙时,我会抓取属于 is_live == true 的那面墙的每个问题。我现在的目标是通过使用 is_live == true 查找墙上的每个问题并将 is_live 更新为 false 来创建一种“清除”所有问题的方法。

但是,我不知道查找和更新每个适当对象的最佳实践/方法。 (这将是一项受限功能,仅适用于具有“管理员”权限的人。)我应该:

  1. 添加一个链接到新创建的 WallController 动作 像下面这样?

    def clear_wall
      @wall = Wall.find(params[:id])
      @problems = @wall.problems.where(:is_live => true)
      @problem.each {|p| p.update_attribute(:is_live => false) }
    
      redirect_to(walls_url)
    end
    
  2. 添加一个form_for,提交执行相同的控制器代码?

  3. 向 Wall 模型添加一个新方法来处理这个问题?

我可能在这方面想得太多了,但在我跌跌撞撞地走上一条过于复杂的道路之前,我会很感激一些方向,这会导致未来出现问题。

【问题讨论】:

    标签: ruby-on-rails jquery-mobile rails-activerecord


    【解决方案1】:

    除了将在 URL 中的 ID 之外,您不需要向服务器传递任何数据,因此使用 link_to 应该没问题。

    当您更改服务器上的数据时,使用:method =&gt; :post 将此方法设为 POST - 更改数据而不使用 POST 是个坏主意

    如果你不需要特殊的视图,你也可以使用:remote =&gt; true来使用AJAX提交表单到这个URL。否则,您问题中的redirect_to 就足够了。

    有关如何构建您的 link_to 的更多信息,请参阅 ActionView 文档

    然后我将直接在您的控制器中实现逻辑(如下所示)

    使用update_all 更新数据库中的许多对象

    ActiveRecord 有一个 update_all 方法,您可以调用 ActiveRecord::Relation

    它不是load the models from the DB, or call callbacks,但由于将任何非 false 设置为 false 在功能上等同于将所有内容设置为 false,因此使用它可能适合您的目的。

    Wall.find(params[:id]).problems.update_all(:is_live =&gt; false)

    您可以向update_all 提供条件参数

    Wall.find(params[:id]).problems.update_all(:is_live =&gt; false, "is_live = true")

    或者先执行 where ,但这将首先从数据库加载所有数据,在您的情况下似乎没有必要。这里要注意的重要一点是,update_all 方法适用于 ActiveRecord::Relation 而不是 ActiveRecord::Base

    Wall.find(params[:id]).problems.where(:is_live =&gt; true).update_all(:is_live =&gt; false)

    【讨论】:

    • Emma,将我指向 update_all 非常有用,看起来确实是执行更新的一种更简洁的方式,但实际上我不确定如何构建视图来处理这个问题。 link_to vs form_for,应该是POST还是PUT等
    • @IanWhalen 我已经更新了我的答案(几次!)所以希望它现在对你的实际问题更有意义。
    • 类似link_to "Clear Wall", clear_wall_url(@wall.id), :method =&gt; :post
    • 对于这个问题的未来读者,值得注意的是,我还必须使用 guides.rubyonrails.org/routing.html#adding-more-restful-actions 讨论的新路由更新 routes.rb
    猜你喜欢
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-04
    • 2022-01-05
    • 2019-03-12
    • 1970-01-01
    • 2011-02-25
    相关资源
    最近更新 更多