Rendering and custom routes

Quick, probably n00bish question, but I can't seem to figure it out.

I am developing a contact management application, and while I am using REST, I have also defined a custom route to make it more understandable to the end user:

map.resources :contacts
map.details 'details/:id', :controller => 'contacts', :action => 'edit' # CRM-type apps allow editing contact details on the viewing page, instead of a separate show/edit page

Anyways, the issue is when a record contains invalid data. GIven the following action:

   def update
     @contact = Contact.find(params[:id])
     if @contact.update_attributes(params[:contact])
       flash[:notice] = "Contact information was updated"
       redirect_to contacts_url
       render :action => "edit"

the address bar displays http://mysite/contacts/1, which results in a Missing Template if the user accidently hits enter (as I don't have a Show action, Edit takes it's place). Is there something I need to add to the render method to make sure that my route is kept? I don't want the user to see contacts/1 but details/1. I tried changing it to redirect_to details_path(@contact), but then no error messages are displayed when the page reloads.

- Wayne

What does your form look like? For that matter, look in the log and see
if you are submitting to contacts or details. I suspect you are
submitting to details.

But, my other guess / suggestion is to add :controller => "details" to
your render line.


According to the log, it's rendering contacts (e.g. http://localhost:3000/contacts/1)
, which is the issue because the URL used to GET the edit template is http://localhost:3000/details/1
. Here's the form:

<%= error_messages_for :contact %>
<div id="details">
   <%= content_tag('h1', @contact.full_name) %>
   <div id="contacts-tab">
     <% form_for @contact do |f| %>
         <label for="first_name">First Name:</label>
         <%= f.text_field :first_name %>
       <%# Remaining tags snipped for brevity %>
         <%= submit_tag "Save Contact" %>
     <% end %>
   <div id="notes-tabs">
     <%= link_to '+ Add Note', new_notes_path(:contact_id => @contact)
     <% if @contact.notes.any? %>
       <% @contact.notes.each do |note| %>
             <%=h note.body %>
             <br />Posted <%=h
distance_of_time_in_words_to_now(note.created_at) %>
       <% end %>
     <% end %>

"details" isn't a controller, it's just a static part of a named route
(so I can pretty up the URL and have it display http://mysite/details/
1 instead of http://mysite/contacts/1/edit):

map.details "details/:id", :controller => "contacts", :action => "edit"

I'm sure I'm just forgetting to add a line somewhere to render the
named route instead of the regular route, I'm just not sure where said
line should go :slight_smile:

- Wayne

Wayne Molina wrote:

     <% form_for @contact do |f| %>

This is why you are posting to the contact path instead of the details
path. It is just taking all the defaults and assumptions but you want
something different. (In particular, where to post to).

You need to change the form_for @contact to something else. Here is a
sample from the documentations:

<% form_for :person, @person, :url => { :action => "update" } do |f| %>

Notice that they specify the type :person as well as the variable to
pull the initial values from. But they add in a URL. You need to do
something similar. Probably something like :url =>
details_path(@contact) -- but I'm kinda guessing. I always have to play
with these things for a bit to get something that works.

The "rake routes" command helps me.

Another way to get a handle on this is to view the page in the browser.
On the form, the submit or action is the URL you will post to. That is
what you are trying to change.

Good luck.