Как мне написать метод поиска Rails через цепочку ассоциаций принадлежащих вам? - PullRequest
1 голос
/ 15 января 2020

Я использую Rails 5.1. Как мне написать метод поиска, когда есть цепочка ассоциаций "own_to"? У меня есть следующие модели ...

class Plan < ApplicationRecord
    ...
  has_many :plan_items, :dependent => :destroy


class PlanItem < ApplicationRecord
    ...
  belongs_to :offer, :optional => false


class Offer < ApplicationRecord
  belongs_to :package, :optional => false


class Package < ApplicationRecord
  has_and_belongs_to_many :items

Я хочу написать искатель, который получает все планы с элементом с id = "blah". Но приведенное ниже не работает ...

[19] pry(main)> Plan.joins(plan_items: :offer).joins(packages: :item).where(:item => {:id => "abac"}).count
ActiveRecord::ConfigurationError: Can't join 'Plan' to association named 'packages'; perhaps you misspelled it?
from /Users/davea/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.2.1/lib/active_record/associations/join_dependency.rb:188:in `find_reflection'

Как мне написать искатель при наличии цепочки принадлежащих принадлежностей?

Ответы [ 2 ]

1 голос
/ 15 января 2020

Во-первых, возможно, ваше имя таблицы неверно. Во-вторых, чтобы передать метод между belong_to ассоциацией, вы можете использовать делегат

0 голосов
/ 15 января 2020

Я предполагаю, что PlanItem - это таблица соединения между Plan и Item (это будет соответствовать соглашению об именах Rails). Это можно сделать аккуратно с помощью through ассоциаций и областей. Я бы сделал это так ...

class Plan < ApplicationRecord
  has_many :plan_items, dependent: :destroy
  has_many :items, through: :plan_items

  scope :blah_items { items.id_of_blah }

class PlanItem < ApplicationRecord
  belongs_to :offer, optional: false
  belongs_to :item

class Item < ApplicationRecord
  scope :id_of_blah { where(id: 'blah') }

Тогда вы можете назвать это так ... Plan.with_blah_items или, если у вас была активная коллекция записей планов, вы могли бы использовать область, чтобы сузить ее plans.with_blah_items.

Поскольку ассоциации ActiveRecord будут возвращать отношения ActiveRecord, вы можете связать их с любыми другими активными методами записи (например, Plan.first.items.where(item: { id: 'blah' }) Области действия просто делают его красивым и аккуратным.:)

Если PlanItem - это , а не таблица соединения между Планом и Предметом, первое, что вы должны сделать, это переименовать ее. Это не просто лучшая практика, rails тратит много времени, предполагая, как называются вещи, и это может вызвать ошибку. После того, как вы переименуете его, вы должны создать таблицу соединения между Планом и Элементом под названием PlanItem. Если объединение между этими таблицами не имеет смысла для архитектуры вашего приложения, вы всегда можете объединить through связей вместе, но это будет запахом кода.

Если вы не хотите связываться с областями видимости , вы всегда можете просто сделать такой запрос plan.items.where(items: { id: 'blah' }).

Надеюсь, это поможет!

...