2017-01-22 4 views
0

У меня есть модель заказа, принадлежащая модели UploadStation. И Загрузочная будет использоваться два раза в таблице Order, так это выглядит:Rails 5 - Несколько внешних ключей относятся к одной и той же таблице

class CreateLoadingStations < ActiveRecord::Migration[5.0] 
    def change 
    create_table :loading_stations do |t| 
     t.integer :type 
     t.string :comp_name1 
     t.string :street 
     t.string :street_num 
     t.string :zip_code 
     t.string :city 

     t.timestamps 
    end 
    end 
    end 



class CreateOrders < ActiveRecord::Migration[5.0] 
     def change 
     create_table :orders do |t| 
      t.string :status 
      t.belongs_to :loading_station, class_name: "LoadingStation", index: true, foreign_key: "loading_station_id" 
      t.belongs_to :unloading_station, class_name: "LoadingStation", index: true, foreign_key: "unloading_station_id" 

      t.timestamps 
     end 
     end 
    end 

Когда я позволил запустить рельсы БД: мигрировать я получил эту ошибку: ActiveRecord :: StatementInvalid: PG: : UndefinedTable: ERROR: отношение «unloading_stations» не существует

Mmmmmm, похоже, что имя_класса не было обнаружено правильно. Имя класса должно быть одинаковым в обоих утверждениях, правильно?

Пусть проверить модель загрузки станции:

class LoadingStation < ApplicationRecord 
end 

Хорошо, я изменить миграцию CreateOrders:

t.belongs_to :loading_station, class_name: "LoadingStation", index: true, foreign_key: "unloading_station_id" 

Теперь, когда я позволил запустить рельсы БД: мигрировать я получил эту ошибку: ActiveRecord :: StatementInvalid: PG :: DuplicateObject: ERROR: ограничение «fk_rails_5294e269cc» для отношения «заказы» уже существуют

Хорошо, я понимаю, что внешний ключ в базе данных, похоже, идентичен, и база данных отклоняет задачу миграции.

Но в чем смысл опции foreign_key: когда я определяю, какие разные имена foreign_key, когда база данных обнаруживает два одинаковых?

Приложение:

Вот моя модель заказа:

class Order < ApplicationRecord 
end 

Заключительный вопрос

И в конце - среди сообщений об ошибках - Я хочу иметь два Внешние ключи, указывающие к той же таблице.

+0

Как выглядит ваша модель 'Order'? У вас на самом деле определена ассоциация 'unloading_station'? – usha

ответ

0

Похоже, что вы не создали модель разгрузки_station.

+0

Да, я не хочу создавать дополнительные модели. Я хочу, чтобы только два внешних ключа указывали на одну и ту же таблицу. Я думаю, что синтаксис после ** t.belongs_to ** неверен. –

0

я не получил какую-либо ошибки на создание миграции с следующими:

t.belongs_to :loading_station, class_name: "LoadingStation", index: true, foreign_key: "loading_station_id" 

t.belongs_to :unloading_station, class_name: "LoadingStation", index: true, foreign_key: "unloading_station_id" 

и таблица заказа выглядит следующим образом:

Order(id: integer, status: string, loading_station_id: integer, unloading_station_id: integer, created_at: datetime, updated_at: datetime) 

поэтому он имеет необходимые идентификаторы, которые вам нужны!

+0

хорошо, я не могу следовать вашему подходу –

0

Я думаю, вы смешиваете то, что должно быть в миграции, и что должно быть в модели (и я не имею в виду это в отрывочном смысле, поэтому, пожалуйста, не принимайте это так).

я сколотить рельсы 5 проекта для вас, чтобы продемонстрировать то, что я думаю, что вы хотите достичь:

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

Это то, что я построил быстро:

# app/models/order.rb 
class Order < ApplicationRecord 
    belongs_to :loading_station, optional: true 
    belongs_to :unloading_station, optional: true 
end 

# app/models/station.rb 
class Station < ApplicationRecord 
end 

# app/models/loading_station.rb 
class LoadingStation < Station 
    has_many :orders 
end 

# app/models/unloading_station.rb 
class UnloadingStation < Station 
    has_many :orders 
end 

Как вы можете видеть модели LoadingStation и UnloadingStation наследуют Station модель. Модель Station получает таблицу в базе данных.

# db/migrate/20170826085833_create_orders.rb 
class CreateStations < ActiveRecord::Migration[5.1] 
    def change 
    create_table :stations do |t| 
     t.string :comp_name1 
     t.string :street 
     t.string :street_num 
     t.string :zip_code 
     t.string :city 
     t.string :type, null: false 
     t.timestamps 
    end 
    end 
end 

Столбец типа определяется как :string и содержит имя класса из подклассов моделей, либо LoadingStation или UnloadingStation.

И миграции заказов таблица выглядит следующим образом:

# db/migrate/20170826085833_create_orders.rb 
class CreateOrders < ActiveRecord::Migration[5.1] 
    def change 
    create_table :orders do |t| 
     t.belongs_to :loading_station, null: true, index: true 
     t.belongs_to :unloading_station, null: true, index: true 
     t.string :status 
    end 
    end 
end 

Как вы можете видеть, что ссылается на LoadingStation.id и UnloadingStation.id. Я не был уверен, были ли эти атрибуты обязательными, поэтому я установил их в null: false в определениях столбцов и optional: true в модели Order.

Чтобы проверить, что это работает, я создал один Загрузочные, один UnloadingStation и один заказ семян базы данных:

# db/seeds.rb 
loading_station_1 = LoadingStation.create!(
    comp_name1: "Loading Station 1", 
    street: "Park Ave", 
    street_num: "300", 
    zip_code: 10001, 
    city: "NY" 
) 

unloading_station_4 = UnloadingStation.create!(
    comp_name1: "Unloading Station 4", 
    street: "Madison Ave", 
    street_num: "204", 
    zip_code: 10001, 
    city: "NY" 
) 

Order.create!(
    loading_station: loading_station_1, 
    unloading_station: unloading_station_4, 
    status: "delivered" 
) 

Чтобы проверить все это, просто создать базу данных, запустить миграцию и выполнить семена:

rails db:create 
rails db:migrate 
rails db:seed 

Чтобы проверить результат вживую открыть rails console:

irb(main):001:0> pp Station.all 

Station Load (0.3ms) SELECT "stations".* FROM "stations" 
[#<LoadingStation:0x007fcb8ac39440 
    id: 1, 
    comp_name1: "Loading Station 1", 
    street: "Park Ave", 
    street_num: "300", 
    zip_code: "10001", 
    city: "NY", 
    type: "LoadingStation", 
    created_at: Sat, 26 Aug 2017 09:06:53 UTC +00:00, 
    updated_at: Sat, 26 Aug 2017 09:06:53 UTC +00:00>, 
#<UnloadingStation:0x007fcb8ac39288 
    id: 2, 
    comp_name1: "Unloading Station 4", 
    street: "Madison Ave", 
    street_num: "204", 
    zip_code: "10001", 
    city: "NY", 
    type: "UnloadingStation", 
    created_at: Sat, 26 Aug 2017 09:06:53 UTC +00:00, 
    updated_at: Sat, 26 Aug 2017 09:06:53 UTC +00:00>] 

irb(main):002:0> pp Order.all 

Order Load (0.2ms) SELECT "orders".* FROM "orders" 
[#<Order:0x007fcb8bca2700 
    id: 1, 
    loading_station_id: 1, 
    unloading_station_id: 2, 
    status: "delivered">] 

irb(main):003:0> order = Order.first 

Order Load (0.2ms) SELECT "orders".* FROM "orders" ORDER BY "orders"."id" ASC LIMIT ? [["LIMIT", 1]] 
=> #<Order id: 1, loading_station_id: 1, unloading_station_id: 2, status: "delivered"> 

irb(main):004:0> pp order.loading_station 

LoadingStation Load (0.2ms) SELECT "stations".* FROM "stations" WHERE "stations"."type" IN ('LoadingStation') AND "stations"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] 
#<LoadingStation:0x007fcb8c0e4390 
id: 1, 
comp_name1: "Loading Station 1", 
street: "Park Ave", 
street_num: "300", 
zip_code: "10001", 
city: "NY", 
type: "LoadingStation", 
created_at: Sat, 26 Aug 2017 09:06:53 UTC +00:00, 
updated_at: Sat, 26 Aug 2017 09:06:53 UTC +00:00> 

irb(main):005:0> pp order.unloading_station 

UnloadingStation Load (0.3ms) SELECT "stations".* FROM "stations" WHERE "stations"."type" IN ('UnloadingStation') AND "stations"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]] 
#<UnloadingStation:0x007fcb8a36a378 
id: 2, 
comp_name1: "Unloading Station 4", 
street: "Madison Ave", 
street_num: "204", 
zip_code: "10001", 
city: "NY", 
type: "UnloadingStation", 
created_at: Sat, 26 Aug 2017 09:06:53 UTC +00:00, 
updated_at: Sat, 26 Aug 2017 09:06:53 UTC +00:00> 

irb(main):006:0> pp order.status 

"delivered" 

Надеюсь, это поможет вам. Я проверил код в github, вы можете получить доступ к нему по адресу https://github.com/JurgenJocubeit/SO-41796815.

Смежные вопросы