Может ли область в has_many полностью заменить соединение по умолчанию? - PullRequest
0 голосов
/ 01 марта 2019

У меня есть модель со сложным объединением:

class Submission < ApplicationRecord
  has_many :histories,
           ->(s) { where(/* A complex query */) },
           class_name: 'SubmissionFieldHistory'
end

Я бы хотел, чтобы этот объемный запрос заменил условия по умолчанию, которые генерируются ActiveRecord, однако, похоже, что добавил к условиям.

Есть ли простой способ сказать has_many :histories, :but_join_it_how_i_say?

1 Ответ

0 голосов
/ 01 марта 2019

Предположение:

Если под «условиями по умолчанию» подразумевается условие SQL по умолчанию WHERE HISTORIES_TABLE.submission_id = SOME_SUBMISSION_ID.

Решение 1:

Чтобы указать пользовательский запрос для has_many, используйте unscope:

class Submission < ApplicationRecord
  has_many :histories,
    ->(s) { unscope(:where).where(/* A complex query */) },
    class_name: 'SubmissionFieldHistory'
end

unscope(:where) выше удалит все / все предыдущие WHERE SQL-запросы в цепочке, один из которых включает в себя WHERE HISTORIES_TABLE.submission_id = SOME_SUBMISSION_ID по умолчанию, из которого вы хотите удалить.

Использование:

submission = Submission.find(1)
submission.histories
# SubmissionFieldHistory Load (5.5ms)  SELECT  "submission_field_histories".* FROM "submission_field_histories"
#   WHERE /* A complex query */ LIMIT $1  [["LIMIT", 11]]

Решение 2:

Однако, поскольку unscope(:where) удаляет все предыдущие WHERE условия, оно также затем удаляет условие, предоставленное default_scope (если у вас есть default_scopeвнутри SubmissionFieldHistory).Для того, чтобы он также работал для default_scope, вы можете использовать вместо него более конкретный unscope(where: SOME_ATTRIBUTE), как показано ниже:

app / models / submission_field_history.rb

class SubmissionFieldHistory < ApplicationRecord
  # example: (default to not fetching anymore "deleted" records)
  default_scope { where(is_deleted: false) }

  belongs_to :submission
end

app / models / submission.rb

class Submission < ApplicationRecord
  has_many :histories,
    ->(s) { unscope(where: :submission_id).where(/* A complex query */) },
    class_name: 'SubmissionFieldHistory'

Использование:

submission = Submission.find(1)
submission.histories
# SubmissionFieldHistory Load (5.5ms)  SELECT "submission_field_histories".* FROM "submission_field_histories"
#   WHERE "submission_field_histories".is_deleted = false
#   AND /* A complex query */ LIMIT $1  [["LIMIT", 11]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...