Xullnn
Xullnn

Reputation: 405

What the difference between find_by_product_id(params[:id]) vs find_by(params[:product_id])

Now I have three models: Product, Cart, CartItem. Here's the related methods and associations:

cart.rb

class Cart < ApplicationRecord
   has_many :cart_items
   has_many :products, :through => :cart_items, :source => :product

cart_item.rb (it has 2 related integer columns, :product_id & :cart_id)

class CartItem < ApplicationRecord
   belongs_to :cart
   belongs_to :product 

application_controller.rb

class ApplicationController < ActionController::Base

  helper_method :current_cart

  def current_cart
      @current_cart ||= find_cart
  end

  private

  def find_cart
      cart = Cart.find_by(id: session[:cart_id])
      if cart.blank?
         cart = Cart.create
      end
      session[:cart_id] = cart.id
      return cart
  end
end

In carts_controller.rb I defined a method to delete specific cart_item in carts#index page:

class CartsController < ApplicationController

  def destroy_one
      @cart_item = current_cart.cart_items.find_by_product_id(params[:id])
      @product = @cart_item.product
      @cart_item.destroy
  redirect_to :back

In the first line of destroy_one method, I can use find_by_product_id(params[:id]) to get the right cart_item

Then I tried find_by(product_id: params[:id]) , it works too.

But if I use find_by(params[:product_id]),something went wrong. When I click delete button, it won't raise an exception, but it will delete another cart_item. It seems rails randomly picked a cart_item and delete it.


Obviously, find_by(params[:product_id]) worked incorrectly here.

My question is:

In this case, I confused with how rails find the right object step by step ? In one Cart, there's many cart_items and products, its reasonable to locate a cart_item by using :product_id. But what's the difference between :

find_by_product_id(params[:id]) vs find_by(params[:product_id])

Respectively, how they work?

Upvotes: 0

Views: 81

Answers (1)

Philipp Meissner
Philipp Meissner

Reputation: 5482

The problem is that you're using find_by(params[:product_id]) wrong. You have to pass the key you want to search for explicitly like so:

find_by(product_id: params[:product_id])

User.find_by(id: 1)
-> User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]

Respectively you can use it as you stated already:

find_by_product_id(params[:product_id])

User.find_by_id(1)
-> User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]

As you can see, both approaches generate the very same SQL query.

Upvotes: 1

Related Questions