views:

161

answers:

5

If I'm on a route alias such as /register and I have a form error and I render :new, is it possible for the path to be /register still?

At the moment it is rendering /new

I could do a redirect_to register_path but then I would lose the params?

It's making the following test fail:

  Scenario: Try registering with a bad staff number
Given I am on the registration page
When I fill in "email" with "[email protected]"
And I fill in "First Name" with "Kevin"
And I fill in "last name" with "Monk"
And I fill in "Employee Number" with "something barking123"
And I press "Register"
Then I should be on the registration page
And I should see "Your employee ID number looks incorrect."
A: 

The Rails Way is to render the "new" (i.e. register) action again, since you have created the object, the form will contain the previously entered values as well as error messages. If you redirect, you would have to save the object in the session or the database before doing the redirect. When diverging from convention, it's always good to be sure you're doing so for a good reason.

fullware
A: 

Calling render from an action will mean that the URL will remain unchanged from whatever was GET'd or POST'd. The reason the URL is /new is because 'Register' must be POST'ing to /new. If you want this feature to pass, you should change "Then I should be on the registration page" to be "Then I should be on the new registration page" and write the corresponding web step, in my opinion.

Ryan Angilly
A: 

If you really want this, then you could merge your 'create' action into your 'new' action, and your 'update' action into your 'edit' action. You'd then need to check the request type and handle it accordingly.

This would achieve what you're asking for. Also, people would be able to use the "error" URL and still go to a valid page. That is, even after getting an error, they could copy/paste the URL and there'd be a valid GET page for it.

That being said, this is a major hack and not something I recommend you do. You'll have to do a lot of legwork and the upside is tiny.

Edit: example..

def new
  if request.get?
    @user = User.new

  elsif request.post?
    @user = User.new(params[:user])
    if @user.save
      redirect_to users_path
    else
      render :new
    end
  end
end

You'd also need to add custom routes.

Jamie Appleseed
A: 

Really, this looks like a one line fix in the test. (Why do you prefer being on the /register page?).

If it's really important, you could also stash params in the session var temporarily.

Michael Glass
+1  A: 

An alternative would be to set up two "register" routes. One that accepts only GET requests (and goes to the :new action) and the other that accepts only POST requests (and goes to the create action, but renders the same template as for new).

This might look like:

map.get_register 'register', :controller => :registrations, 
                 :action => :new, :conditions => { :method => :get }
map.post_register 'register', :controller => :registrations, 
                 :action => :create, :conditions => { :method => :post }

Then in your controller:

def new
   @registration = Registration.new
   # renders the 'registrations/new' template
end
def create
   @registration = Registration.new(params[:registration])

   # render the 'registrations/new' template if we fail validation
   return render(:action => :new) unless @registration.save
   # otherwise renders the "create" template which is likely a thank-you
end

There seems to be more in a similar vein on this question: http://stackoverflow.com/questions/1083798/use-custom-route-upon-model-validation-failure

Taryn East
Hi Taryn,THat's exactly what I did in the end.Thanks for your answer.Kevin.
Kevin Monk