ruby-on-rails - 如何让对象链接到对象?

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

我对 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/

相关文章:

ruby-on-rails - has_one/has_many 具有依赖销毁功能,但对键使用不同的名称

ruby-on-rails - Mongoid多对多问题

json - Bookshelf.js 哪里有 json 列 Postgresql

javascript - 为什么测试中文件中的 js 不起作用?

python - 为什么我的模型的 "on_delete=models.CASCADE,"不生成级联外键约束?

postgresql - 求PostgreSQL中每个X由Y组成的比例?

c# - 如何将更改从模型获取到模型 View 中?

ruby-on-rails - Rails 测验应用程序的正确模型关联

ruby-on-rails - Rails : named_scope, lambda 和 block

ruby-on-rails - 为什么我在添加 Refinery CMS 后尝试播种时收到 "uninitialized constant RefineryPage"