I think you're mixing up what should to be in the migration and what should to be in the model (and I don't mean this in a derogative way so please don't take it that way).
I have put together a rails 5 project for you to demonstrate what I think you want to achieve:
In summary I believe you're looking to have both the loading and unloading stations stored in the one table, but reference them separately as attributes of the order. In other words you're looking for single-table inheritance.
This is what I built quickly:
# 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
As you can see the LoadingStation
and UnloadingStation
models inherit the Station
model. The Station
model gets a table in the database.
# 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
The type column is defined as a :string
and holds the class name of the subclassed models, either LoadingStation
or UnloadingStation
.
And the orders table migration looks like this:
# 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
As you can see it references the LoadingStation.id
and UnloadingStation.id
. I wasn't sure whether or not these attributes were mandatory, so I set them to null: false
in the column definitions and optional: true
in the Order
model.
To test that this works I created one LoadingStation, one UnloadingStation and one Order in the database seeds:
# 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"
)
To test all this, simply create the database, run the migrations and execute the seeds:
rails db:create
rails db:migrate
rails db:seed
To test the result live open the 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"
I hope this helps you. I have checked the code into github, you can access it at https://github.com/JurgenJocubeit/SO-41796815.
Order
model look? Do you actually haveunloading_station
association defined?