如何获取链接到对象的对象?

时间:2017-08-08 22:13:59

标签: ruby-on-rails postgresql model foreign-keys ruby-on-rails-5

我对Rails中的某些事情感到困惑(使用Rails 5)。我有这个模型

class MyEventActivity < ApplicationRecord
  belongs_to :event_activity
end

我要做的是获取链接到它的所有对象的列表,换句话说,所有&#34; event_activity&#34;对象。我认为这会做到这一点

my_event_activities = MyEventActivity.all.pluck(:event_activity)

但它给了我这个SQL错误

   (2.3ms)  SELECT "event_activity" FROM "my_event_activities"
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column "event_activity" does not exist
LINE 1: SELECT "event_activity" FROM "my_event_activities"

如何获取链接到MyEventActivity对象的对象?请注意,我不想要ID,我想要整个对象。

编辑:这是所要求的PostGres表

eactivit=# \d event_activities;
                                            Table "public.event_activities"
          Column          |            Type             |                           Modifiers
--------------------------+-----------------------------+----------------------------------------------------------------
 id                       | integer                     | not null default nextval('event_activities_id_seq'::regclass)
 name                     | character varying           |
 abbrev                   | character varying           |
 attendance             | bigint                      |
 created_at               | timestamp without time zone | not null
 updated_at               | timestamp without time zone | not null

1 个答案:

答案 0 :(得分:2)

EventActivity.joins(:my_event_activities).distinct

返回已关联EventActivity条记录

的所有MyEventActivity个对象

或者你已经尝试过的更多内容:

EventActivity.where(id: MyEventActivity.all.pluck(:event_activity_id).uniq)

但第一个因其简洁和性能而更受欢迎。

更新以解释为什么第一个选项应该是首选

TL; DR更快,更易读

假设我们有100 event_activities,除了最后一个(id: 100)之外的所有my_event_activities都有100 my_event_activities,总共9900 EventActivity.where(id: MyEventActivity.all.pluck(:event_activity_id).uniq)

SELECT "my_event_activities"."event_activity_id" FROM "my_event_activities"执行两个SQL查询:

event_activity_id将返回9900个非唯一Array#uniq的数组。我们希望将此减少为唯一ID以优化第二个查询,因此我们调用SELECT "event_activities".* FROM "event_activities" WHERE "event_activities"."id" IN (1, 2, 3, ... 97, 98, 99),它在大型阵列上有自己的性能成本,将9900减少到99.然后我们可以调用第二个查询:{{1} }

EventActivity.joins(:my_event_activities).distinct只执行一个SQL查询:SELECT DISTINCT "event_activities".* FROM "event_activities" INNER JOIN "my_event_activities" ON "my_event_activities"."event_activity_id" = "event_activities"."id"。一旦我们进入数据库,我们就不必切换回Ruby来执行一些昂贵的过程,然后再次返回数据库。 joins旨在在这种情况下执行这些类型的可链接和可组合查询。

可以使用简单的基准检查性能差异。实际的Postgres数据库加载了100个event_activities,其中99个有100个my_event_activities

require 'benchmark/ips'
require_relative 'config/environment'

Benchmark.ips do |bm|
  bm.report('joins.distinct') do
    EventActivity.joins(:my_event_activities).distinct
  end

  bm.report('pluck.uniq') do
    EventActivity.where(id: MyEventActivity.all.pluck(:event_activity_id).uniq)
  end

  bm.compare!
end

结果:

Warming up --------------------------------------
      joins.distinct     5.922k i/100ms
          pluck.uniq     7.000  i/100ms
Calculating -------------------------------------
      joins.distinct     71.504k (± 3.5%) i/s -    361.242k in   5.058311s
          pluck.uniq     73.459  (±13.6%) i/s -    364.000  in   5.061892s

Comparison:
      joins.distinct:    71503.9 i/s
          pluck.uniq:       73.5 i/s - 973.38x  slower
<9>慢973倍:-O! joins方法意味着用于这样的事情,这是Ruby中的一个令人愉快的案例,其中更具可读性也更高效。