Sunday, May 27, 2012

[Rails] How to load a selection list into the method new of a controller?

Hi friends!
I'm relatively new with Rails and I'm struggling for a long time with this problem (it should have a pattern solution but until now I didn't find it): I have the following models: Institution, City, State and Country.

class Country < ActiveRecord::Base
  has_many :states
  has_many :cities, :through => :states
end
# == Schema Information
# Table name: countries
#  id         :integer         not null, primary key
#  sigla      :string(2)       not null
#  nome       :string(30)      not null

class State < ActiveRecord::Base
  has_many   :cities
  has_many   :institutions, :through => :cities
  belongs_to :country
end
# == Schema Information
# Table name: states
#  id         :integer         not null, primary key
#  country_id :integer     not null
#  sigla      :string(2)      not null
#  nome       :string(40)  not null

class City < ActiveRecord::Base
  has_many :institutions
  belongs_to :country
  belongs_to :state
end
# == Schema Information
# Table name: cities
#  id          :integer         not null, primary key
#  country_id  :integer         not null
#  state_id    :integer         not null
#  nome        :string(40)      not null

class Institution < ActiveRecord::Base
  belongs_to :city
end
# == Schema Information
# Table name: institutions
#  id                 :integer         not null, primary key
#  city_id            :integer

The table states is pre-loaded with all Brazil's states (seed):

State.create!(country_id: Country.find(:first, conditions: "sigla = 'ZZ'").id, nome: 'desconhecido', sigla: 'ZZ')
State.create!(country_id: Country.find(:first, conditions: "sigla = 'BR'").id, nome: 'Distrito Federal', sigla: 'DF')
State.create!(country_id: Country.find(:first, conditions: "sigla = 'BR'").id, nome: 'Acre', sigla: 'AC') ... and so on...
City.create!(country_id: Country.find(:first, conditions: "sigla = 'BR'").id,
             state_id: State.find(:first, conditions: "nome = 'desconhecido'").id,
             nome: 'desconhecida')
City.create!(country_id: Country.find(:first, conditions: "sigla = 'BR'").id,
             state_id: State.find(:first, conditions: "nome = 'Paraná'").id,
             nome: 'Cianorte')
City.create!(country_id: Country.find(:first, conditions: "sigla = 'BR'").id,
             state_id: State.find(:first, conditions: "nome = 'São Paulo'").id,
             nome: 'Campinas') ... and so on...

 When I create a new institution, I have to select a city from a drop-down list. But I need to constrain this list with the state the cities belong to. So I tried this way:

routes.rb:
Application.routes.draw do
  get "states/index"
  resources :institutions do
    post 'selstate'
  end
  resources :cities
  resources :states, only: :index

rake routes:
          states_index GET    /states/index(.:format)                                      states#index
institution_selstate POST   /institutions/:institution_id/selstate(.:format)        institutions#selstate
             institutions GET    /institutions(.:format)                                         institutions#index
                            POST   /institutions(.:format)                                         institutions#create
       new_institution GET    /institutions/new(.:format)                                  institutions#new

Institution new template:
<%= form_for(@institution) do |f| %>
  <fieldset>
  <legend>Cidade onde se localiza a instituição</legend>
    <div class="field">
      Estado selecionado:
      <%= @estado_selecionado %>
      <%= link_to "Selecionar estado...", states_path %><br />
      <%= f.label :cidade %>
      <%= f.collection_select :city_id, @cities, :id, :nome, include_blank: true %>
      <!--%#= link_to "Incluir nova cidade", new_city_path %--> (to be included later)
    </div>
<% end %>
  </fieldset>

State index template:
<h3>Selecione um estado</h3>
<table>
  <% @states.each do |s| %>
    <tr>
      <td><%= s.sigla %></td>
      <td><%= s.nome %></td>
      <td><%= button_to 'Selecionar', institution_selstate_path( s ) %></td>
    </tr>
  <% end %>
</table>

class StatesController < ApplicationController
  def index
    @states = State.where('nome != ?', 'desconhecido').order(:nome)
  end

class InstitutionsController < ApplicationController
  def new
    @institution = Institution.new
    if session[:state_id].nil?
      session[:state_id] = State.find_by_sigla('ZZ').id
    end
    @estado_selecionado = State.find(session[:state_id]).nome
    if @estado_selecionado == 'desconhecido'
      @cities = City.all
    else
      @cities = City.where('state_id = ?', session[:state_id]).order(:nome)
    end
    respond_to do |format| ...
    end
  end

  def create
    @institution = Institution.new(params[:institution])
    respond_to do |format|
      if @institution.save ...
    end

  def selstate
    session[:state_id] = params[:id]
    redirect_to new_institution_path
  end
 end

As you can see, after select the state, I return to the Institution new action. My hope was to have a state selected and the cities list constrained to those pertaining to that state. But nothing happens. I receive the same screen before the state selection. I have many similar situations in my system... all waiting for this solution  :-) .
Is my approach correct?
Any help will be very appreciated. Sorry my bad english!
Thanks in advance!

Luis

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/twaxTGlguiIJ.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home


Real Estate