Rails - check if record exists in has_many association

26,351

Solution 1

Try:

current_user.items.exists?(params[:id])

Or

current_user.items.exists?(@item.id)

Solution 2

Extending @lei-liu's answer here. One can find if the record exists among the many or not, through: current_user.items.exists?(params[:id])

At the same time, exists? allows one to filter through the columns besides id, and also allows for more complicated conditions, like the following:

current_user.items.exists?('id > 3')
current_user.items.exists?(name: 'some_name')
Share:
26,351

Related videos on Youtube

user4584963
Author by

user4584963

Updated on July 15, 2022

Comments

  • user4584963
    user4584963 almost 2 years

    I'm not sure if my question is worded correctly.

    I have three models: User, Item, and UserItem.

    user has_many :user_items
    user has_many :items, through :user_items
    
    item has_many :user_items
    item has_many :users -> {uniq}, through :user_items
    item belongs_to :user
    
    user_item belongs_to :user
    user_item belongs_to :item
    

    I need a way to see if a user has an item to make if statements in my item views But here's the catch, user_items have enum status: [ :pending, approved]. So I need to see if a current_user has a certain :pending item.

    For example when a user visits item1's view page I have the item_controller's show action declare @item = Item.find_by_id(params[:id]). But then what can I do with this @item to see if a user has this item?

  • user4584963
    user4584963 about 8 years
    I believe enum automatically adds scope
  • tkz79
    tkz79 about 8 years
    This wasn't written to be something to copy and paste, it was written as an example to show the OP how to write and use a model method... and how to use his pending enumerator. The select call is a little wasteful given the uniq limitation, but someone else has already shown how to check if something exists. Way to hate without offering anything of value @AndreyDeineko.
  • Andrey Deineko
    Andrey Deineko about 8 years
    1) you do not need self. 2) select would load the whole pending user_items collection into memory prior evaluating the block, thus, having tons records in collection it could potentially overwhelm the memory. 3) in this case you do not need to return. 4) you could just leave the user_items.pending.select {|s| s.user == user}.count > 0 since it will already return the boolean value. 5) sorry for the form of my first comment - it was the very morning - apologies
  • user4584963
    user4584963 about 8 years
    @AndreyDeineko You mentioned a "conventional" way to accomplish this. What would that be?
  • Andrey Deineko
    Andrey Deineko about 8 years
    @user4584963 by the unconventional I meant the wrong use of return keyword here.
  • tkz79
    tkz79 about 8 years
    @AndreyDeineko - 1+2 - I thought this was a good way to cut down the memory needs - we should only be fetching the user_items for that item, and only those that are pending... I did not know the self was unnecessary!! 3) the return habit comes from C when i took comp sci many years ago - before getting out of programming for over a decade. 4) Was thinking to set him up for more complicated functionality - agreed for this case! 5) All Good... Thanks for returning to clarify! Always enthusiastic to learn the better way!
  • drewish
    drewish over 6 years
    i don't think you want a count query. if you're just checking for existence using .exists? would give you a SELECT ... LIMIT 1 which would stop once a match was found.