2017-01-22 98 views
0

我有一个属于一个LoadingStation模型的订单模型。而在LoadingStation将用于在订单表两次,所以它看起来像: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:错误:关系“unloading_stations”不存在

Mmmmmm,似乎是class_name检测不正确。两个语句中的class_name应该是相同的,对吗?

让检查装车点的模型:

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

看起来您还没有创建卸载模型。

+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) 

所以它有你需要必要的ID!

+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 

正如你可以看到LoadingStationUnloadingStation车型继承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并且保持子类模型的类名,无论是LoadingStationUnloadingStation

而且订单表迁移看起来是这样的:

# 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.idUnloadingStation.id。我不确定这些属性是否是强制性的,因此我将它们设置为列定义中的null: falseOrder模型中的optional: true

要测试这个工程,我创建一个LoadingStation,一个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上访问它。