无法弄清楚如何在Rails中查询二级资源

时间:2015-03-26 22:14:22

标签: sql ruby-on-rails activerecord

我在查询用户时遇到了麻烦。

我的嵌套资源是:

  resources :users do
    resources :photos do
      resources :pins
    end
  end

1。)我有一个user模型,has_many :photos

2。):photos has_many :pins

我想在用户的照片中有更多针脚列出我的用户。

所以,我试过了:

@members_ordered = User.includes(photos: :pins).group("users.id").group("photos.id").group("pins.id").order('COUNT(pins.id) DESC')

虽然没有工作。有任何想法吗?谢谢你们

1 个答案:

答案 0 :(得分:1)

我有两个观察结果,但都没有直接修复你的例子中的代码。

首先,看看我的输出尝试类似的东西,看起来你要么需要相当复杂的SQL(实际上不是Rails的强项)或几个简单的查询(根据你的应用程序的大小,它可能会打绩效)实现这一目标。

与三个简单查询所需的相比,一个小实验似乎没有显示出一个复杂查询所需的显着差异(<1ms)(如在解决方案一中)

解决方案之一,如果性能不是至关重要,例如,如果这是一个小型,低流量的解决方案,我的本能就是添加User模型{{1这可以让你调用像User.includes(照片::pins).all,然后是has_many :pins, through: :photos这样的东西,尽管如我所提到的,这会导致数据库使用更多。

解决方案二,如果性能很重要,我的建议是根据用户模型缓存引脚数。这可以像存储它的额外数据库列一样简单,并且具有后台进程(使用delayed_job或类似)每次更改时重新计算计数(因此,user.pins.count中可能after_create模特。

这样做的好处是缓慢,耗时的查询只在值发生变化时运行,其余的时间,值从单表Pin中解除,这应该花费相当多的时间比解决方案一个或更复杂的查询少一点时间。

这些都不够完美,我认为最优雅高效的工作方式是使用内置函数和简单查询的组合:

第三个解决方案,它在某种程度上汇集了这两个选项,是Rails的SELECT选项。由于它有两个级别,我无法在一个查询中看到将所有这些包含在内的本机方式,因此我们将自动为每个counter_cache生成一个计数,然后将其添加以获取用户计数。

  1. 创建迁移以将pins_count字段添加到Photo模型,因此,在终端中键入;

    Photo
  2. rails g migration AddPinsCountToPhotos pins_count:integer 型号的belongs_to :photo行更新为;

    Pin
  3. 现在,每次创建或删除belongs_to :photo, counter_cache: true 时,Pin的{​​{1}}列都会更新。

    现在,获取用户的值;

    1. 创建迁移以将pins_count字段添加到User模型,因此,在终端中键入;

      pins_count
    2. 现在我们需要在Photo模型中创建一个方法,我们会在每次保存图钉时运行该方法,因此请将其添加到rails g migration AddPinsCountToUsers pins_count:integer 模型中;

      Photo
    3. 最后,我们需要告诉Rails在创建或更新引脚时调用它。我们使用一种简单的方法来执行此操作,该方法仅调用Photo模型中的操作;

      def update_user_counts
        total_photos = self.user.photos.sum(:pins_count)
        self.user.update_attribute(:pins_count, total_photos)
      end
      
    4. 现在,每当保存一个引脚时,它会自动更新Photo s after_save :update_photo_counts def update_photo_counts photo.update_user_counts end ,然后我们的新方法总计来自所有Photo的{​​{1}}个对于该用户,并将其保存到pins_count s pins_count