1
\$\begingroup\$

I am trying to do a self-join. I generated this migration to make a correct primary. This code works, but I'm not sure if this is the best way to do things.

class CreateFeedstocks < ActiveRecord::Migration[5.0]
 def change
 create_table :feedstocks do |t|
 t.string :code
 t.float :measure_one
 t.float :measure_two
 t.float :measure_three
 t.string :description
 t.integer :primary_feedstock_id, index: true
 t.timestamps
 end
 add_foreign_key :feedstocks, :feedstocks,
 column: :primary_feedstock_id,
 primary_key: :id
 end
end

One feedstock has one primary_feedstock and one primary_feedstock has many feedstocks.

Wayne Conrad
3,3041 gold badge18 silver badges38 bronze badges
asked Dec 24, 2016 at 19:40
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Can it be nested? Like primary_feedstock has_many feedstocks, where feedstock has_many other feedstocks? \$\endgroup\$ Commented Dec 27, 2016 at 13:57
  • \$\begingroup\$ @AleksandrK. No, a feedstock belongs to a primary feedstock, but a primary feedstock can have many feedstocks \$\endgroup\$ Commented Dec 27, 2016 at 21:08
  • 1
    \$\begingroup\$ Personal opinion - the only thing - consider to make measure_one, measure_two, measure_three as an array field in db. what if you will need 4-5-6? \$\endgroup\$ Commented Dec 28, 2016 at 15:16
  • \$\begingroup\$ @AleksandrK. The measures are actually thickness, width and length. I choose one, two and three because the measure_one could be diameter or thickness, because some feed-stocks has diameter and others has thickness. Thanks for your comment c: \$\endgroup\$ Commented Dec 28, 2016 at 15:28

1 Answer 1

2
\$\begingroup\$

Does the format provided in the Rails Guides not work for you?

# Model ------------------------------------------------------------------------
class Feedstock < ApplicationRecord
 has_many :feedstocks, foreign_key: "primary_feedstock_id"
 belongs_to :primary_feedstock, class_name: "Feedstock"
end
# Migration --------------------------------------------------------------------
class CreateFeedstocks < ActiveRecord::Migration[5.0]
 def change
 create_table :feedstocks do |t|
 t.references :primary_feedstock, index: true
 t.timestamps
 end
 end
end

EDIT: So I'm still not clear on the difference between add_foreign_key and t.references. According to this comment on SO, t.references will not create a foreign key constraint, but that was written 5 years ago, and the part of the Guides that the commenter mentioned is no longer there.

The API docs are abundantly clear about add_foreign_key creating a foreign key constraint at the database level; unfortunately, they're not so clear about t.references.

In any case, you will have to decide for yourself how to design your application. I've heard some people say that depending on ActiveModel is ‘the Rails Way’, but I haven't seen that position stated anywhere in the official docs. Alternately, others will tell you that implementing these checks at the database level is more performant and reliable, and I can't argue with that. I think in the end, the choice comes down to how strictly you believe in Rails' convention-over-configuration philosophy, and whether you're willing to sacrifice a little abstraction for performance and reliability.

EDIT 2: It appears that add_foreign_key alone is not sufficient to create a table column. You'll need t.references either way, followed by either the foreign_key: true option or a separate add_foreign_key directive.

answered Jul 27, 2017 at 6:51
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.