carmen-ruby / carmen-rails

NOT ACTIVELY MAINTAINED Rails adapter for Carmen (provides country_select and subregion_select)
MIT License
215 stars 159 forks source link

country_select in nested model doesn't get filled when editing record #12

Closed jandillmann closed 12 years ago

jandillmann commented 12 years ago

I have a Customer model with an associated Address model. The Customer model accepts nested attributes for the Address. The Address has fields for country and region.

If I create a new Customer with it's associated Address, the Country and Region are saved to the database, but when I edit a record, the fields are not getting filled, i.e., the saved Country and Region are not selected.

Am I using this wrong or is it a bug, because when the country fields are in the main model and not in the associated model, everything works fine.

The view:

<%= semantic_form_for [:admin, @customer] do |f| %>
    <%= f.inputs "Address" do %>
        <%= f.semantic_fields_for :address, f.object.address || f.object.build_address do |address| %>
            <%= address.input :country %>
            <li id="customer_address_attributes_region_input" class="country input optional">
                <%= address.label :region, :class => 'label' %>
                <%= render partial: 'region_select', locals: {country: address.object.country} %>
            </li>
        <% end %>
    <% end %>
<% end %>

And the partial _region_select.html.erb:

<div id="address_region_wrapper">
    <% country ||= params[:country] %>
    <% country = Carmen::Country.coded(country) %>

    <% if country.nil? %>
        <em>Please select a Country above.</em>
    <% elsif country.subregions? %>
        <%= subregion_select(:customer_address_attributes, :region, country, {}, {:name => "customer[address_attributes][region]"}) %>
    <% else %>
        <%= text_field(:customer_address_attributes, :region, :name => "customer[address_attributes][region]") %>
    <% end %>
</div>
jim commented 12 years ago

I think the problem you're having is that the partial is looking for an object called customer_address_attributes which doesn't exist. Try passing the address into the partial and then using it as the first argument to the subregion_select call:

<div id="address_region_wrapper">
    <% address ||= :address %>
    <% country ||= params[:country] %>
    <% country = Carmen::Country.coded(country) %>

    <% if country.nil? %>
        <em>Please select a Country above.</em>
    <% elsif country.subregions? %>
        <%= subregion_select(address, :region, country, {}, {:name => "customer[address_attributes][region]"}) %>
    <% else %>
        <%= text_field(address, :region, :name => "customer[address_attributes][region]") %>
    <% end %>
</div>

And then where you embed the partial:

<%= render partial: 'region_select', locals: {country: address.object.country, address: address} %>

There may be cleaner ways to handle passing the values in, but this should be a step in the right direction.

jandillmann commented 12 years ago

Thanks for your anwer, Jim. Although it sounds reasonable, unfortunately that didn't change anything for me.

I now solved it with country_select_tag and subregion_select_tag as follows:

The view:

<%= semantic_form_for [:admin, @customer] do |f| %>
  <%= f.inputs "Address" do %>
    <%= f.semantic_fields_for :address, f.object.address || f.object.build_address do |address| %>
      <li id="customer_address_attributes_country_input" class="country input">
        <%= address.label :country, :class => 'label' do %>
          <%= Destination.human_attribute_name(:country) %>
        <% end %>
        <%= country_select_tag "customer[address_attributes][country]", address.object.try(:country), :prompt => "Please select a Country." %>
      </li>
      <li id="customer_address_attributes_region_input" class="country input optional">
        <%= address.label :region, :class => 'label' %>
        <%= render partial: 'region_select', locals: {address: address.object} %>
      </li>
    <% end %>
  <% end %>
<% end %>

And the partial:

<div id="customer_address_region_code_wrapper">
  <% address ||= params[:address] %>
  <% country ||= params[:country] || address.country %>
  <% country = Carmen::Country.coded(country) %>

  <% if country.nil? %>
    <em>Please select a Country above.</em>
  <% elsif country.subregions? %>
    <%= subregion_select_tag("customer[address_attributes][region]", address.try(:region), country) %>
  <% else %>
    <%= text_field_tag("customer[address_attributes][region]", address.try(:region)) %>
  <% end %>
</div>

The only problem remaining is that the prompt sentence is not displayed for the country_select_tag. Is there another way to accomplish this?

jim commented 12 years ago

I just pushed a fix for the lack of prompt support in country_select_tag. Give it a try and see if that fixes it for you.

jandillmann commented 12 years ago

Wow, this works like a charm. Thank you very much!

jim commented 12 years ago

Glad to hear it.

flynfish commented 11 years ago

@jim I also ran into the same issue and was able to solve it by modifying @jandillmann code.

= f.simple_fields_for :addresses, defaults: {input_html: {class: "span3"}} do |address|

  = address.hidden_field :content_type, :value => "Residence"
  = address.input :address1
  = address.input :address2
  = address.input :city
  = address.input :state, :wrapper_html => {:id => 'wrap-state'} do
    = subregion_select_tag "person[addresses_attributes][0][state]", address.object.try(:state), "US", :prompt => "Select if applicable"
  = address.input :zip_code
  = address.input :country_code, :wrapper_html => {:id => 'wrap-country'} do
    = country_select_tag "person[addresses_attributes][0][country_code]",
        address.object.try(:country_code),
        priority: %w(US),
        prompt: 'Please select a country'