Steve Grossi
Steve Grossi

Reputation: 2795

In ruby on rails, how to group records by tag when records have multiple tags

I'm using Rails 3.0 and the acts_as_taggable_on gem. I have a Candy model and candies can have multiple tags for flavors. Let's say

Candy1.tags #['apple', 'orange']
Candy2.tags #['orange', 'banana']
Candy3.tags #['apple', 'kiwi']

I want a list of tags with associated candies below them, like so:

Apple

Orange

...etc.

I've tried

Candy.all.group_by{ |candy| candy.tags }

but that treats the array of tags as a single entity, returning something like this:

['apple', 'orange']

['orange', 'banana']

Lacking a group_by_each method, whats the best way to accomplish this? Another Stack Overflow question explains how to do this in memory with simple hashes, but I wonder if there's a more database-oriented way to do it with ActiveRecord associations.

Upvotes: 3

Views: 1486

Answers (3)

azoo_b
azoo_b

Reputation: 120

In rails api documentation that group_by is for collecting enumerable. I think you need to try a more classic array iterator like the following since you've strings data

in views/candy/index.html.erb

    <% @candys.each do |candy| %>
    <%= candy.name %>
    <% end %>

    <%for tag in candy.tags %>
     <li> <%= tag.name(or flavor %> </li>    #tag.name_attribute
    <% end %>

  <% end %>

Let me know if it works

Upvotes: 0

Michelle Tilley
Michelle Tilley

Reputation: 159105

candies = Candy.all.inject({}) do |memo, candy|
  candy.tags.each do |tag|
    memo[tag] ||= []
    memo[tag] << candy
    memo
  end
end

Now candies is a hash like this:

{
  'apple' => [Candy1, Candy3],
  'orange' => [Candy1, Candy2],
  ...
}

Which you can iterate over nicely:

candies.each do |key, value|
  puts "Candy tag: #{key}"
  value.each do |candy|
    puts " * #{candy}"
  end
end

Upvotes: 0

JCorcuera
JCorcuera

Reputation: 6834

You can iterate over the candies and store them on a hash base on the tag:

grouped = {}
Candy.all.each do |candy|
  candy.tags.each do |tag|
    grouped[tag] ||= []
    grouped[tag] << candy
  end
end

At the end you will get:

{'apple' => [candy1, candy2], 'orange' => [] ...}

Hope this helps you

Upvotes: 4

Related Questions