1

I've been dabbling around in rails and I'm having a hard time understanding how a foreign key automatically get's populated in a table of a model when I push something into it. For example, in a 1:N table relationship of Cart to Ingredients(assuming no carts were made), if I code this:

# create cart and couple of ingredients
cart1 = Cart.create()
jelly = Ingredient.create()
pb = Ingredient.create()

# push jelly, and pb, into cart1
cart1.ingredients << jelly
cart1.ingredients << pb

# pb and jelly cart_id is now populated
pb.cart_id
>>1
jelly.cart_id
>>1

How does rails populate the foreign id, cart_id, column without me having to do anything, except push the ingredient into the cart?

dimakura
  • 7,575
  • 17
  • 36
Justin Reyes
  • 153
  • 1
  • 1
  • 11
  • 2
    You already have a cart ID after the create, and Rails knows the relationships you've defined--nothing particularly magical about it. – Dave Newton Oct 03 '15 at 20:09
  • I guess the thing I cant quite figure out is that the column is "cart_id". But to find cart1's id it would be "cart1.id". Is there a convention that find's a "modelname_id" table and INSERTS it like that? – Justin Reyes Oct 03 '15 at 20:17
  • 2
    Yes. The entire Rails is about convention over configuration. Foreign key field name convention is _id. – The Ancient Oct 03 '15 at 21:20
  • @JustinReyes Note that you should probably be using instance variables and not local variables when creating an instance of a class. Thus, you should use "@cart = Cart.create()", so that it is an instance variable. While not critically necessary for a code snippet like this, it will be important as you build an app. – Richard_G Oct 05 '15 at 21:00

2 Answers2

2

You can imagine the process like this:

# creates cart with id=1
cart = Cart.create

# creates ingredient with card_id=nil
jelly = Ingredient.create

# It's one-to-many relation, which knows that
# the name of the foreign key is cart_id.
# How does it know?
# Rails uses conventional logic here:
# if you don't name things explicitly then Rails
# will guess them for you.
# Name of the model is Cart, so the foreign key is cart_id.
cart.ingredients

# One-to-many relation receives some object.
# Relation asks object: do you have method cart_id=?
# Object replies: yes, I have
# Relation then takes primary key (id in this case)
# from cart (=1) and places it into object's cart_id field.
cart.ingredients << jelly

jelly.cart_id # => 1
dimakura
  • 7,575
  • 17
  • 36
0

As per:

By convention, Rails assumes that the column used to hold the foreign key on this model is the name of the association with the suffix _id added. The :foreign_key option lets you set the name of the foreign key directly

This, although describing specifically for the belongs_to association, explains how Rails treats foreign_keys.

Each object you have in your system can be associated by the ActiveRecord ORM. If you have a has_many, belongs_to or has_and_belongs_to_many relationship, ActiveRecord will populate the foreign key based on its own logic (described above), or if you explicitly set it in the models.

So when you have:

@cart.ingredients #-> ActiveRecord method populates foreign key of child objects with cart_id
Richard Peck
  • 76,116
  • 9
  • 93
  • 147