Rails: запрос для двухэтапного отношения через join-table + имеет много отношений - PullRequest
0 голосов
/ 26 декабря 2018

Я работаю над улучшением схемы базы данных.В настоящее время я использую сквозную структуру has_many с моделью / таблицей земель, моделью / таблицей услуг доставки и моделью / таблицей постзоны, которая соединяет таблицы земель и доставки.

Has many through

Я могу сделать запрос следующим образом:

@shippingservices = @cart.available_shipping_services.includes(:lands, :postzones).where('postzones.land_id = ?', params[:id])

И получить все транспортные услуги для данной земли (страны).

Но в этом случае я получаю много повторений вТаблицу postzone и обслуживание довольно сложно.Было бы намного проще, если бы я мог собирать земли в зонах с большим количеством земель, чем подключать службы доставки к зоне.Как и в этой схеме:

Join table + has many

Как запросить в этом случае все службы доставки для данной земли?

Дляобъединяющий стол я бы сделал что-то вроде:

@shippingservices = @cart.available_shipping_services.joins(:lands => :zones).where('lands_zones_join.land_id = ?', params[:id])

что не работает, так как я получаю:

Mysql::Error: Unknown column 'lands_zones_join.zone_id' in 'where clause': SELECT `shippingservices`.* FROM `shippingservices` 
INNER JOIN `zones` ON `zones`.`id` = `shippingservices`.`zone_id` 
INNER JOIN `lands_zones` ON `lands_zones`.`zone_id` = `zones`.`id` 
INNER JOIN `lands` ON `lands`.`id` = `lands_zones`.`land_id` 
INNER JOIN `lands_zones` `zones_lands_join` ON `zones_lands_join`.`land_id` = `lands`.`id` 
INNER JOIN `zones` `zones_lands` ON `zones_lands`.`id` = `zones_lands_join`.`zone_id` 
WHERE (weightmin <= 50 AND weightmax >= 50 AND height >= 3 AND shippingservices.shippingcarrier = '1') AND (length >= 210 AND width >= 149) AND (lands_zones_join.zone_id = '2')

это вообще возможно? как я могузаставить это работать?

Заранее спасибо!

ОБНОВЛЕНИЕ

models / shippingservices.rb

class Shippingservice < ActiveRecord::Base
  belongs_to :zone
  has_many :lands, :through => :zone
end

app/models/zone.rb

class Zone < ActiveRecord::Base
  has_and_belongs_to_many :lands, :join_table => "lands_zones"
  has_many :shippingservices
end

app / models / landszone.rb

class LandsZone < ActiveRecord::Base
  belongs_to :land
  belongs_to :zone
end

app / models / land.rb

class Land < ActiveRecord::Base
  has_and_belongs_to_many :zones, :join_table => "lands_zones"
  has_many :shippingservices, :through => :zones
end

дБ / схема.rb

create_table "lands", :force => true do |t|
  t.string   "name"
end

create_table "lands_zones", :force => true do |t|
  t.integer  "land_id"
  t.integer  "zone_id"
end

add_index "lands_zones", ["land_id"], :name => "index_lands_zones_on_land_id"
add_index "lands_zones", ["zone_id"], :name => "index_lands_zones_on_zone_id"

create_table "shippingservices", :force => true do |t|
  t.integer  "zone_id"
  t.string   "name"
  t.string   "shippingcarrier"
end

  create_table "zones", :force => true do |t|
    t.string   "name"
  end

Я уменьшил его, удалив временные метки и т. д., но сохранил все необходимые части.

1 Ответ

0 голосов
/ 26 декабря 2018

@shippingservices = @cart.available_shipping_services.joins(:lands => :zones).where('lands_zones_join.land_id = ?', params[:id])

Таблица lands_zones_join в предложении where неверна.Rails рассматривает это как производное имя таблицы и применяет два дополнительных объединения, видимых здесь:

INNER JOIN `lands_zones` `zones_lands_join` ON `zones_lands_join`.`land_id` = `lands`.`id` 
INNER JOIN `zones` `zones_lands` ON `zones_lands`.`id` = `zones_lands_join`.`zone_id`

Это приводит к дублированию в результатах запроса.

Отношения от Shippingservice доLand правильно настроен в моделях и схемах.Поэтому мы можем соединить таблицы напрямую и запросить саму таблицу земель для идентификатора:

@cart.available_shipping_services.joins(:lands).where(lands: {id: params[:id]})

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...