我对 Rails 中的某些东西感到困惑(使用 Rails 5)。我有这个模型
class MyEventActivity < ApplicationRecord
belongs_to :event_activity
end
我想做的是获取链接到它的所有对象的列表,换句话说,所有“event_activity”对象。我以为这样就可以了
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
最佳答案
EventActivity.joins(:my_event_activities).distinct
返回所有具有关联MyEventActivity
记录的EventActivity
对象
或者更符合您已经尝试过的内容:
EventActivity.where(id: MyEventActivity.all.pluck(:event_activity_id).uniq)
但第一个因其简洁和性能而更可取。
更新以解释为什么应该首选第一个选项
TL;DR 更快,更易读
假设我们有 100 个 event_activities
,除最后一个 (id: 100
) 之外的所有事件都有 100 个 my_event_activities
,总共有 9900 个 my_event_activities
。
EventActivity.where(id: MyEventActivity.all.pluck(:event_activity_id).uniq)
执行两个 SQL 查询:
SELECT "my_event_activities"."event_activity_id"FROM "my_event_activities"
这将返回一个包含 9900 个非唯一 event_activity_id
的数组。我们想将其减少为唯一 ID 以优化第二个查询,因此我们调用 Array#uniq
,它在大型数组上有其自身的性能成本,将 9900 减少到 99。然后我们可以调用第二个查询:SELECT "event_activities".* FROM "event_activities"WHERE "event_activities"."id"IN (1, 2, 3, ... 97, 98, 99)
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
慢了 973 倍:-哦! joins
方法旨在用于此类事情,这是 Ruby 中令人高兴的案例之一,可读性更高,性能也更高。
关于ruby-on-rails - 如何让对象链接到对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45578819/