adamscott adamscott - 7 months ago 10
Ruby Question

how do rails associations get set?

I always seem to have trouble with this concept. I get what associations allow you to do, I just never seem to be able to tell if the associations are set in an application.

For example, I generated a scaffold for line_items and before I ran my migration, I set the belongs_to and has_many methods in the correct models, and then ran my migration.

After running my migration, I look at my schema and I can't tell if there are any associations set. To me it does not seem like it because I don't see the schema setting any relationships.

Do the has_many and belongs_to methods actually set the association? Or are they there for developers reading the code to understand the relationship?

How would my schema look if the associations were set properly? Do I need to rollback my last migration and include the correct indexes?

create_table "carts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "line_items", force: :cascade do |t|
t.integer "product_id"
t.integer "cart_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "products", force: :cascade do |t|
t.string "title"
t.text "description"
t.string "image_url"
t.decimal "price", precision: 8, scale: 2
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

Answer

it's very simple to tell if the association is set up properly or not through your schema. basically the model has belongs_to should have the corresponding table that contains the foreign_id. For example in the schema you post, it's easy to see that the lineItem belongs to 'Product' and Cart, because it has cart_id and product_id(two foreign id).

activerecord is not a black magic, all has_many and belongs_to do is just dynamically adds a method to the model class, which translate the query to raw sql for you and map the result to ruby object. however it is your responsibility to set up the database table correctly. Because after all, activerecord use SQL to query data following rails convention.

update

I think what you mean is the helper method in your migration file such as

t.belongs_to product, index: true, foreign_key: true

this line of code is also not a black magic, it is a helper method rails provide to make your life much easier. It is equivalent to do three simple things to create your database table.

  1. create a foreign_id depends on your input, in the above example, it will be product_id. equivalent to t.integer product_id
  2. add an index on the foreign_id, because usually you query out the associated data a lot by using the foreign_id, add an index will improve your efficiency. equivalent to add_index "xxx", ["product_id"], name: "index_xxxs_on_product_id"
  3. at the end the foreign_key: true is going to set up an database constrains for your foreign_id, so that if there is still one row in your child table related to one row in your parent table, the row in your parent table will not be accidentally deleted. this is equivalent to add_foreign_key :xxxs, :products

so as a conclusion, using add_foreign_key :articles, :authors will not make anything look special in your schema, because ActiveRecord is just a translator to make your life easier when you deal with sql database, it can only do the thing sql database can do, not anything special. the idea of association in database is just saving a foreign_id in one table so that you can query the related data in another table by using the foreign_id.