Software Engineer && Email Developer
relationships made sense, but the addition to many-to-many—
—relationships are where it got weird.
. Currently, an Order with an attribute of
could only have one value. Meaning, one MenuItem per Order. Can you imagine if you had to get back in line and start a new order for each item you wanted to buy at a coffee shop?
relationship came in.
has many through
needed to be an array. This is where a four,
model comes in.
acts as a join table, with foreign keys to the
models. In this example, think of each OrderItem record has a transaction instance, representing one
at a time.
records with the same
. I was a step closer to figuring out what I needed.
model made sense.
to see all the items in that order? My app had a
model too. How do you build a has_many through a relationship when there are more than three models?
directly. ActiveRecord does that work for me. Since an
, referencing the
would gives me direct access to
class User < ApplicationRecord has_secure_password has_many :orders end class Order < ApplicationRecord belongs_to :user has_many :order_items has_many :menu_items, through: :order_items end class OrderItem < ApplicationRecord belongs_to :order belongs_to :menu_item end class MenuItem < ApplicationRecord has_many :order_items has_many :orders, through: :order_items end
object. At first, everything seemed to be working. But after looking closer at the console, I realized the transaction was getting rolled back and orders were not being saved to the database.
key was listed in my strong params, but I was getting a "
is not permitted error".
order = Order.create(user_id: 1, name_for_pickup: "Rachel", menu_item_ids: [1,2,3])
order.menu_items // [1,2,3]
order.menu_items << item
param. I thought I needed to create an order. Instead, I needed to create an order,
find the menu items by id (menu_items_id, which was the unpermitted param) and shovel them into the array
def create @order = Order.create(order_params) if @order.save redirect_to order_path(@order) else render :new end end
def create @order = Order.create(order_params) items_to_add = params[:order][:menu_item_ids] items_to_add.each do |item_id| if item_id != "" item_id = item_id.to_i item_to_add = MenuItem.find_by_id(item_id) @order.menu_items << item_to_add end end if @order.save redirect_to order_path(@order) else render :new end end
are also something to look out for. All params are strings, which may cause downstream effects if you are expecting an integer or boolean.
can be submitted in a
model, the transaction will fail (and not write to your database, yay!) if an attribute of
was within your params.
will give more information into what validations may be causing errors. For example, in my app, an
must have as
(barista) user_id associated with it. Running
in the console would not tell me much, but running
would print out an error like A User must exist.
(an empty object, which will not validate because there is no
order = Order.create()
will return false.