Best way to client-side load or hide state/province drop down when country is changed?

Maybe I'm just trying too hard, because I have done this plenty of
times with plain old javascript before Rails entered my life. But now
that I'm trying to work within the Rails system of form_for and such,
I am finding that what should be a simple task has become arduous
beyond compare. I'm ready to tear out what little hair I have left,
and I have yet to find anything online that addresses what I thought
would be a common scenario.

So, the scenario:
A user create/edit page. When a user selects US or Canada, the drop
down loads accordingly. If he selects a different country, the
dropdown disappears. When the form is submitted, the user and his
address are saved accordingly.

User: has_one :address
Address: has_one :state, has_one :country


I got it working by foregoing a form_for selector for this attribute,
and using a manually loaded html selector instead. Seems to work as
desired, though it feels a bit hackish.

i dont think that's 'hackish'.
Basically you're foregoing some automated magic for more control and
which in this case you needed.

True true! Just happy to get it working.

If you want a solution that is more Rails-centric...

First, I created some helper methods just for convenience. (I only
needed the state_options one but created the others for testing this
solution). The xxx_options simply creates an acceptable collection
for populating a Rails select. The xxx_option_tags return a string of
option tags with the line breaks removed. That's necessary for their
inclusion in a js function below:

in application_helper.rb:
  def state_options
    Address::STATES.collect{|state| [state, state]}

  def province_options
    Address::PROVINCES.collect{|state| [state, state]}

  def state_option_tags
    options_for_select(state_options).gsub("\n", "")

  def province_option_tags
    options_for_select(province_options).gsub("\n", "")

I've got an address partial because I will capture addresses for all
kinds of different things (people, customers, businesses, etc). My
address partial just consists of a normal 'fields_for :address'.
Here's the part relevant to the discussion:

    <%= :state, state_options %>
    <%= f.text_field :postal_code %>
    <%= f.country_select :country, ['United States',
'Canada'], :selected=>'United States' %>
    <%= observe_field :address_country,
                      :function=> "switch(value){ case 'United
States': $('address_state').show();$
('address_state').update('#{state_option_tags}'); break; case
'Canada': $('address_state').show();$
('address_state').update('#{province_option_tags}'); break; default: $
('address_state').hide();}" %>

Okay, so what's going on... I'm making use of the prototype library
packaged with Rails and the baked-in "observe_field" helper. This
helper observes the country select field and fires on a change (the
country select is rendered with US and Canada at the top before an
alphabetical listing of countries, and US is selected by default).
The :function=>... part is passing a js-function that will become the
method responsible for handling the change in the observe field. It
will be wrapped in a function block that looks like: function(object,
value) {}. That's where the 'value' field comes from. The rest of
the string is just a switch-statement that loads the appropriate
values into the select box or hides it all together.

The #{state_option_tag} is where the application_helper.rb comes into
play. That is evaluated at run time to give the select options you
need. The net effect is that the js swaps out the <option> tags in
the address_select field.