the12
the12

Reputation: 2415

How to get an object from via its association with an ActiveRecord query?

Using Rails 5.0:

class User < ApplicationRecord
  belongs_to :cart, {:optional => true}
end

class Phone < ApplicationRecord
  has_many :cart_items
end

class CartItem < ApplicationRecord
  belongs_to :cart, {:optional => true} #has cart_id as column 
  belongs_to :phone, {:optional => true} #has phone_id as column
end

class Cart < ApplicationRecord
  has_one :user
  has_many :cart_items
end

My app works as follows. There are users (User), that have carts (Cart), and in those carts have cart items (CartItem). In each of those cart items there is information regarding the cart including what phones are purchased (Phone).

I am currently using an .each loop to loop through user.cart.cart_items, if it returns a cart item has params[:phone_id], then it would update it and break from the loop.

user_items = @user.cart.cart_items
if user_items.any?{|x| x.phone_id == params[:phone_id].to_i}

  user_items.each do |x|
  if x.phone_id == params[:phone_id].to_i
    x.update_attributes(:quantity_sold => params[:quantity].to_i)
    break
  end
  end

end

Although it works, I was wondering whether there was a way to use a database query to find all associated phones associated with the user_items (@user.cart.cart_items). Note: @user is just the current user logged in.

I tried using @user.cart.cart_items.where(:phone_id => 1), and it worked, but when trying to retrieve the phone from there via the query @user.cart.cart_items.where(:phone_id => 1).phone, it returned the error undefined method 'phone' for #<CartItem::ActiveRecord_AssociationRelation:0x007fa38a461128>.

I checked to see whether my associations were set up correctly via (cart_item.phones, and phone.cart_items, and they worked fine (cart_item = instance of CartItem and phone = instance of Phone).

Is there a way I can use a database query from an association to find all user cart items (@user.cart.cart_items) that have a phone id of x (params)? Note: I need the actual object, so I can look through fields of the phone (i.e.: @user.cart.cart_items.phone.brand_name.)

Upvotes: 0

Views: 54

Answers (1)

wesley6j
wesley6j

Reputation: 1403

This gives you related CartItems:

user_items_with_matching_phone = @user.cart.cart_items.where(phone_id: x)

To get the first item's phone:

user_items_with_matching_phone.first.phone

To update the first item (basically what you did in the each loop):

user_items_with_matching_phone.first.update_attributes(quantity_sold: params[:quantity].to_i)

However, you can not do user_items_with_matching_phone.phone because user_items_with_matching_phone is more similar to an array than a single object. You can get the length if by user_items_with_matching_phone.size

Upvotes: 2

Related Questions