benoitr
benoitr

Reputation: 6105

Rails - Getting data from a table for each iteration of a loop

Sorry for this newbie question but I cannot figure how I can do this..

I have the following City table

# Table name: cities
#
#  id          :integer
#  name        :string(255)
#  country     :string(255)

(note: I am not using a separate Country table as I use Geokit-rails and think it is simpler to store all Google queries in the same table. However It would be easier to have separate tables to render what I want through a belong_to/has_many association)

In my city/index view I want to loop all the cities for each countries in order to render something like:

United States
  New York
  San Francisco
  Los Angeles
United Kingdom
  London
Spain
  Madrid
...

By now, What I can get is what it provided by scaffolding

Model

def index
  @cities = City.all
end

View

<table>
  <% for city in @cities %>
  <tr>
    <th><%= city.country %></th>    
  </tr>
  <tr>
    <td><%= city.name %></td>
  </tr>
    <% end %>
</table>

Rendering:

United States
  Los Angeles
United States
  New York
...

I didn't find any resource about this. I would be pleased if someone could help me (I don't know with which I have to start: find_by_ /params /each or collection?)

Thanks a lot!

Upvotes: 0

Views: 2674

Answers (3)

dwhalen
dwhalen

Reputation: 1925

I've had success with the group_by method:

@cities.group_by(&:country).each do |country, cities|
  puts country.name
  cities.each do |city|
    puts "-> #{city.name}"
  end
end

Output:

United States
-> New York
-> San Francisco
-> Los Angeles
United Kingdom
-> London
Spain
-> Madrid
-> Barcelona

Of course, you'll probably be doing this in an erb template, but the idea is the same:

<ul>
    <% @cities.group_by(&:country).each do |country, cities| %>
        <li><%= country.name %></li>
        <li>
            <ul>
                <% cities.each do |city| %>
                    <li><%= city.name %></li>
                <% end %>
            </ul>
        </li>
    <% end %>
</ul>

Output:

  • United States
    • New York
    • San Francisco
    • Los Angeles
  • United Kingdon
    • London
  • Spain
    • Madrid
    • Barcelona

Upvotes: 1

Andrei S
Andrei S

Reputation: 6516

The correct way to do this is to create a Country table with id and name and in your City model just keep a country_id to the country, instead of a string

so

class Country < ActiveRecord::Base
  has_many :cities
end

class City < ActiveRecord::Base
  belongs_to :country
end

then you can call Country.includes(:cities) and iterate over them like this in your view:

<% for country in countries %>
  <%= country.name %>
  <% for city in country.cities %>
    <%= city.name %>
  <% end %>
<% end %>

If you still want to use your way, you could do something like

@cities = City.order("country asc")
@countries = @cities.map(&:country).uniq!

<% for country in @countries %>
  <%= country.name %>
  <% for city in @cities %>
    <%= city.name if city.country == country %>
  <% end %>
<% end %>

Upvotes: 3

J-_-L
J-_-L

Reputation: 9177

The official rails guides are an excellent place to start ;)

Upvotes: 0

Related Questions