Nested Routes allow for actions only if IDs match??

Hello,

I'm encountering a very strange issue and I've identified behavior I don't quite understand. I have a design in which a "full model" exists with sub-screens for each of the pages worth of data input. Each screen goes through validation, and then updates the overall model with the validated input, as well as saving the screen's information to a specific "screen" table.

For instance:

class FullQuoteHoModel < ActiveRecord::Base   has_one :full_quote_ho   has_one :full_quote_ho_loc   has_one :full_quote_ho_cov   has_one :full_quote_ho_additional_coverage

end

class FullQuoteHo < ActiveRecord::Base   belongs_to :full_quote_ho_model end

class FullQuoteHoLoc < ActiveRecord::Base   belongs_to :full_quote_ho_model end

class FullQuoteHoCov < ActiveRecord::Base   belongs_to :full_quote_ho_model end

class FullQuoteHoAdditionalCoverage < ActiveRecord::Base   belongs_to :full_quote_ho_model end

FullQuoteHoModel is the "entire" model, with each of the others as "sub-screens" that accept inputs, validate them, save the values to their tables, and also update the accepted, validated inputs into the "entire" model.

I only want index/show/new/destroy in the FullQuoteHoModel, and I only want new/create/edit/update in the sub-screens. I do this in the routes file as follows:

  map.resources :full_quote_ho_models, :except => [:edit, :update, :create], :requirements => {:id => /[0-9]+/} do |full_quote_ho_model|     full_quote_ho_model.resources :full_quote_ho_additional_coverages, :only => [:new, :create, :edit, :update], :requirements => {:id => /[0-9]+/}, :name_prefix => nil     full_quote_ho_model.resources :full_quote_ho_covs, :only => [:new, :create, :edit, :update], :requirements => {:id => /[0-9]+/}, :name_prefix => nil     full_quote_ho_model.resources :full_quote_ho_locs, :only => [:new, :create, :edit, :update], :requirements => {:id => /[0-9]+/}, :name_prefix => nil     full_quote_ho_model.resources :full_quote_hos, :only => [:new, :create, :edit, :update], :requirements => {:id => /[0-9]+/}, :name_prefix => nil   end

Now, when I create a new full quote ho model from the FullQuoteHoModel index screen, I can create each of the screens just fine, as well as the overall model (for testing purposes, there is no validation above, so I create empty records that are assigned system-generated IDs).

When I access any screen from the FullQuoteHoModel, if it has the same ID path as the FullQuoteHoModel, things show up and work as intended. However, if the ID of the screen is not the same as the FullQuoteHoModel, then I receive the following error:

ActionController::RoutingError in Full_quote_hos#edit

Showing app/views/full_quote_hos/edit.html.erb where line #3 raised:

full_quote_ho_url failed to generate from {:action=>"update", :full_quote_ho_model_id=>#<FullQuoteHo id: 4, inception_date: "", building_construction: nil, protection_class: nil, territory: "", policy_form: "", replacement_cost_on_contents: "", occupancy_type: "", building_type: "", applicants_first_name: "", applicants_middle_initial: "", applicants_last_name: "", applicants_date_of_birth: "", applicants_ssn: "", coapplicants_first_name: "", coapplicants_middle_initial: "", coapplicants_last_name: "", coapplicants_date_of_birth: "", coapplicants_ssn: "", property_address_1: "", property_address_2: "", property_zip_code: "", property_county: "", property_city: "", property_state: "", property_city_limits: "", property_address_how_long: "", mailing_address_1: "", mailing_address_2: "", mailing_zip_code: "", mailing_county: "", mailing_city: "", mailing_state: "", previous_address_1: "", previous_address_2: "", previous_zip_code: "", previous_county: "", previous_city: "", previous_state: "", currently_insured: "", current_carrier: "", created_at: "2009-06-23 05:45:03", updated_at: "2009-06-23 05:45:03", full_quote_ho_model_id: 3>, :controller=>"full_quote_hos"}, expected: {:action=>"update", :controller=>"full_quote_hos"}, diff: {:full_quote_ho_model_id=>#<FullQuoteHo id: 4, inception_date: "", building_construction: nil, protection_class: nil, territory: "", policy_form: "", replacement_cost_on_contents: "", occupancy_type: "", building_type: "", applicants_first_name: "", applicants_middle_initial: "", applicants_last_name: "", applicants_date_of_birth: "", applicants_ssn: "", coapplicants_first_name: "", coapplicants_middle_initial: "", coapplicants_last_name: "", coapplicants_date_of_birth: "", coapplicants_ssn: "", property_address_1: "", property_address_2: "", property_zip_code: "", property_county: "", property_city: "", property_state: "", property_city_limits: "", property_address_how_long: "", mailing_address_1: "", mailing_address_2: "", mailing_zip_code: "", mailing_county: "", mailing_city: "", mailing_state: "", previous_address_1: "", previous_address_2: "", previous_zip_code: "", previous_county: "", previous_city: "", previous_state: "", currently_insured: "", current_carrier: "", created_at: "2009-06-23 05:45:03", updated_at: "2009-06-23 05:45:03", full_quote_ho_model_id: 3>}

Extracted source (around line #3):

1: <h1>Editing Full Quote Homeowners: Basic Information</h1> 2: 3: <% form_for(@full_quote_ho) do |f| %> 4: <%= error_messages_for :full_quote_ho, :header_message => "#{@full_quote_ho.errors.count} validation errors prohibited this Full Quote Screen from being validated.", :message => "Please correct the fields in red and try again." %> 5:

This is an issue because currently, a user can create a new FullQuoteHoModel, fill out two screens, then hit Back and go to the FullQuoteHoModel index, maybe create a new FullQuoteHoModel, fill out all screens, then decide to return to the first one and create the remaining two screens. The IDs are then out of sync (which isn't unintended behavior - technically speaking, no matter what the ID of the screen, it belongs to one and only one FullQuoteHoModel) and trying to go back and edit that screen doesn't show up. Is this a routing issue (the generated URLs, maybe)? Or something else?

The index page shows the ability to create or edit screens as follows per FullQuoteHoModel record:

    <% @full_quote_ho_models.each do |full_quote_ho_model| %>     <tr>       <td><%=h full_quote_ho_model.inception_date %></td>       <td><%=h full_quote_ho_model.policy_form %></td>       <td><%=h full_quote_ho_model.applicants_first_name %></td>       <td><%=h full_quote_ho_model.applicants_middle_initial %></td>       <td><%=h full_quote_ho_model.applicants_last_name %></td>       <td><%=h full_quote_ho_model.applicants_ssn %></td>       <td><%=h full_quote_ho_model.property_address_1 %></td>       <td><%=h full_quote_ho_model.property_address_2 %></td>       <td><%=h full_quote_ho_model.property_zip_code %></td>       <td><%=h full_quote_ho_model.property_county %></td>       <td><%=h full_quote_ho_model.property_city %></td>       <td><%=h full_quote_ho_model.property_state %></td>     </tr>     <tr>       <td colspan="1"><%= link_to 'Show', full_quote_ho_model %></td>

      <% if full_quote_ho_model.full_quote_ho != nil %>       <td colspan="2"><%= link_to 'Edit Basic Information', edit_full_quote_ho_path(full_quote_ho_model.id, full_quote_ho_model.full_quote_ho.id) %></td>       <% else %>       <td colspan="2"><%= link_to 'Continue Basic Information', new_full_quote_ho_path(full_quote_ho_model.id) %></td>       <% end %>

      <% if full_quote_ho_model.full_quote_ho_loc != nil %>       <td colspan="2"><%= link_to 'Edit Locations', edit_full_quote_ho_loc_path(full_quote_ho_model.id, full_quote_ho_model.full_quote_ho_loc.id) %></td>       <% else %>       <td colspan="2"><%= link_to 'Continue Locations', new_full_quote_ho_loc_path(full_quote_ho_model.id) %></td>       <% end %>

      <% if full_quote_ho_model.full_quote_ho_cov != nil %>       <td colspan="2"><%= link_to 'Edit Coverages', edit_full_quote_ho_cov_path(full_quote_ho_model.id, full_quote_ho_model.full_quote_ho_cov.id) %></td>       <% else %>       <td colspan="2"><%= link_to 'Continue Coverages', new_full_quote_ho_cov_path(full_quote_ho_model.id) %></td>       <% end %>

      <% if full_quote_ho_model.full_quote_ho_additional_coverage != nil %>       <td colspan="2"><%= link_to 'Edit Additional Coverages', edit_full_quote_ho_additional_coverage_path(full_quote_ho_model.id, full_quote_ho_model.full_quote_ho_additional_coverage.id) %></td>       <% else %>       <td colspan="2"><%= link_to 'Continue Additional Coverages', new_full_quote_ho_additional_coverage_path(full_quote_ho_model.id) %></td>       <% end %>

      <td colspan="1"><%= link_to 'Destroy', full_quote_ho_model, :confirm => 'Are you sure?', :method => :delete %></td>     </tr>

If I try and alter the generated URLs to not include IDs, I receive errors. I know the ordering of the IDs is appropriate. The pathing should be as it currently is: /full_quote_ho_models/#/full_quote_ho/# or /full_quote_ho_models/#/full_quote_ho_locs/#, etc.

Has anyone seen this behavior before?

Have you tried explicitly setting the URL to post to in the form_for? From the trace, it looks like it's trying to generate a route to edit_full_quote_ho without specifying the parent model. [@full_quote_ho_model, @full_quote_ho] might work as well.

--Matt Jones

Matt Jones wrote:

Have you tried explicitly setting the URL to post to in the form_for? From the trace, it looks like it's trying to generate a route to edit_full_quote_ho without specifying the parent model. [@full_quote_ho_model, @full_quote_ho] might work as well.

--Matt Jones

On Jun 23, 2:02�am, Ahad Amdani <rails-mailing-l...@andreas-s.net>

No, I haven't tried explicitly setting the URL. I'm trying to do this the proper way within the Rails framework, and I wanted to utilize the helpers/paths.

[@full_quote_ho_model, @full_quote_ho] didn't work and caused similar issues.

As I said earlier, if the IDs for the parent model and it's nested models are the same, everything works fine - but if not, that's when there is an error. So, I have a feeling it isn't my view code/URLs, but rather the logic behind how I have things routed and/or designed.