JP Silvashy
JP Silvashy

Reputation: 48495

rails if object in an array

I need to check, if for each item in @line_items if it is in different array say @quote_items

Controller:

def index
  @line_items = LineItem.all
  @quote_items = QuoteItem.all
end

View:

<% for line_item in @line_items %>
   <% if @quote_items.include?(line_item) %>
     line_item in quote item! 
   <% else %>
     line_item NOT in quote item! 
   <% end %>
...
<% end %>

Is there an easy way to do this? include? doesn't seem to work the way I want. Seems to just yield false for me all the the time.

Upvotes: 3

Views: 3678

Answers (3)

Max Chernyak
Max Chernyak

Reputation: 37357

Like it was pointed out in discussion above — it depends on which criterion you're comparing objects in 2 arrays.

  • If objects are of the same class (or the same ancestor), then include? will work.
  • If objects are different, and you only want to compare their ids (although this makes little sense), it'd be something like this:

    line_item_ids = @line_items.map(&:id) # array of just the attribute we need
    @quote_items.each do |quote_item|
      if line_item_ids.include?(quote_item.id)
        # line item with the same id found
      else
        # ...
      end
    end
    

    You can do the above with any attribute, not just id.

  • If in both cases your objects are plain strings or symbols, make sure you're converting everything to string or symbol. Sometimes I forget and comparisons end up being false.

Upvotes: 3

nas
nas

Reputation: 3696

You are right it will always return false because you are trying to check if the array of @quote_items has a line item object

@quote_items.include?(line_item)

which obviously will always be false because your @quote_items instance is an array of QuoteItem objects and @line_items instance is an array of LineItem object. So they are always different objects.

I think in this situation you may want to compare some common attribute of quote_item and line_item. For example if you want to compare name attribute then

quote_item_names = @quote_items.map(&:name)

and then

<% if quote_item_names.include?(line_item.name) %>
 line_item in quote item! 
<% else %>
 line_item NOT in quote item! 
<% end %>

Upvotes: 6

Firas Assaad
Firas Assaad

Reputation: 25750

@line_items & @quote_items should return an array that includes the common items between them. @line_items - @quote_items return items that are in @line_items but not in @quote_items.Your code should work though, are you sure there are common items between them? Note that item equality is checked by the == operator, so you might need to provide that for your item class.

Upvotes: 1

Related Questions