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| %>

Cidade onde se localiza a instituição
Estado selecionado: <%= @estado_selecionado %> <%= link_to "Selecionar estado...", states_path %>
<%= f.label :cidade %> <%= f.collection_select :city_id, @cities, :id, :nome, include_blank: true %> (to be included later)
<% end %>

State index template:

Selecione um estado

<% @states.each do |s| %> <% end %>
<%= s.sigla %> <%= s.nome %> <%= button_to 'Selecionar', institution_selstate_path( s ) %>

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 :slight_smile: . Is my approach correct? Any help will be very appreciated. Sorry my bad english! Thanks in advance!

Luis

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

That is not right, a cities country is accessible through the state via @city.state.country.

belongs_to :state end # == Schema Information # Table name: cities # id :integer not null, primary key # country_id :integer not null

Above is not needed.

I have not even read the rest, you have provided much too much information. If you still have a problem then simplify it down to to the smallest amount of code that demonstrates it and post that.

Colin

Thank you for your fast reply! Yes, I agree it isn’t necessary to put a direct relation to country inside the city model. But I did it because sometimes the user will not know to which state a new city belongs to, and at least he will know the country.

Luis

Thank you for your fast reply! Yes, I agree it isn't necessary to put a direct relation to country inside the city model. But I did it because sometimes the user will not know to which state a new city belongs to, and at least he will know the country.

With it in you could get into a situation where @city.country is not the same as @city.state.country. Also note that @country.cities will only include those accessed via state.

Please don't top post, it makes it difficult to follow the thread. Insert you reply at appropriate points in the previous message. Thanks.

Colin

Hmmmm, I didn’t think in this situation… you are right. I will exclude country_id from de city model. Well. Filtering my models to simplify the explanation of my problem, I end up with these:

class State < ActiveRecord::Base has_many :cities has_many :institutions, :through => :cities belongs_to :country end

class City < ActiveRecord::Base has_many :institutions belongs_to :state end

class Institution < ActiveRecord::Base belongs_to :city end

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!(state_id: State.find(:first, conditions: “nome = ‘desconhecido’”).id, nome: ‘desconhecida’) City.create!(state_id: State.find(:first, conditions: “nome = ‘Paraná’”).id, nome: ‘Cianorte’) City.create!(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

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| %>

Estado selecionado: <%= @estado_selecionado %> <%= link_to “Selecionar estado…”, states_path %>
<%= f.label :cidade %> <%= f.collection_select :city_id, @cities, :id, :nome, include_blank: true %>
<% end %>

State index template:

Selecione um estado

<% @states.each do |s| %> <% end %>
<%= s.sigla %> <%= s.nome %> <%= button_to 'Selecionar', institution_selstate_path( s ) %>

class StatesController < ApplicationController def index @states = State.all 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. Is my approach correct?

Thanks! Luis