I have developed contingent country-state select dropdowns, and I'd like to factor out this behavior to an Address model so that I don't have to copy the dynamic behavior (more or less split between view and controller) each and every time I want the user to be able to enter a full address.
Basically I'm trying to dip my toes a little deeper into DRY. But I'm not sure exactly where to embed the behaviors. Do I use the model or the helper to build the necessary forms? Most importantly: where and how can I invoke the dynamic behavior for updating lists of states? Do I need an Address controller, or could it all be done from within the model?
In other words, what I've got now in the view is something like:
# _refine.html.erb
<tr>
<td>
<%= label_tag :dest_country, 'Country: ' %></td><td>
<%= select_tag :dest_country,
options_for_select(Carmen::country_names
<< 'Select a country',
:selected => 'Select a country'),
{:include_blank => true,
:id => 'country_select',
:style => 'width: 180px',
:onchange => remote_function(
:url => {:action => 'update_state_select'},
:with => "'country='+value")} %>
</td>
</tr>
<tr>
<div id="state_select_div">
<td><%= label_tag :dest_state, 'State:   ' %></td>
<td><%= select_tag :dest_state,
options_for_select(Carmen::states('US').collect{
|s| [s[0],s[0]]} << ['Select a state'],
:selected => 'Select a state'),
{:style => 'width: 180px'} %></td>
</div>
</tr>
The update method is in the controller:
# search_controller.rb
def update_state_select
# puts "Attempting to update states"
states = []
q = Carmen::states(Carmen::country_code(params[:country]))
states = q unless q.nil?
render :update do |page|
page.replace_html("state_select_div",
:partial => "state_select",
:locals => {:states => states }
)
end
end
Finally, I've got a partial which is dropped in with the proper names or a blank text field:
# _state_select.html.erb
<% unless states.empty? or states.nil? %>
<%= label_tag :dest_state, 'Select a state' %>
<br/> <%= select_tag :dest_state,
options_for_select(states.collect{|s| [s[0],s[0]]}
<< ['Select a state'],
:selected => 'Select a state'),
{:style => 'width: 180px'} %>
<% else %>
<%= label_tag :dest_state, 'Please enter state/province' %><br />
<%= text_field_tag :dest_state %>
<% end %>
Now, what I'd like to do is to be able to associate an address through the model (say, Person has_one :address) and within the form for creating a new person, be able to use something like
<%= label_tag :name, 'What's your name?' %>
<%= text_field_tag :name %>
<%= label_tag :address, 'Where do you live?' %>
<%= address_fields_tag :address %>
Which could generate the appropriate drop-downs, dynamically coupled together, the results of which would be accessible through Person.address.country and Person.address.state.
Thanks in advance!