19

I have a 'new' form that gets validated in a post model. When the validator kicks in, it renders incorrectly.

The new post page path is at '/posts/new'

On validation, the new post page path is at '/posts' .. I need it to go back to '/posts/new'.

This is my controller:

def create
 @post = current_user.posts.build(params[:post])
 if @post.save
   redirect_to public_post_page_path(@post.public_url)
 else 
   render :action => :new
 end
end

I have a feeling it might have to do with my form. So here is the formtastic first line:

<%= semantic_form_for [:student, post], :html => {:id => "post_form"} do |form| %>
Marc
  • 1,033
  • 2
  • 10
  • 28

2 Answers2

13

This is the correct behavior from rails.

In the create action it simply renders the "new" view file. As such the url will be /posts but the view will correctly display the form. There is nothing wrong with this behavior; and in general rails convention is good form. Also the built in rails errors work if you just render new; however if you redirect they won't display.

If you really feel like you want to go back to that url you need to use:

redirect_to 

instead of render.

Msencenb
  • 5,675
  • 11
  • 52
  • 84
  • 1
    I want to display the errors, so it needs to be render. The reason I need it to go back to /posts/new is a little complex. But basically, in controller for 'def new', I check the twitter validation for the user to determine whether or not to show parts of the form. When it goes to '/posts', I lose this validation. I guess then the question is, is there a way to reload the code in 'new' controller after render? – Marc Jan 08 '12 at 05:40
  • 3
    Create a private controller method to do your setup for new, call it from new and from create before it renders new – house9 Jan 08 '12 at 06:36
  • @Marc Rails, by convention does a `POST` to /posts for creating. You can always violate this convention by posting to /posts/new. – Thong Kuah Jan 08 '12 at 09:33
  • I followed house9 advice. Did this 'before_filter :check_twitter, :only => [:new, :edit, :create, :update]' – Marc Jan 08 '12 at 21:43
  • This is an important answer, because if you're using Rspec and have something like this: page.current_url.should == "http://www.example.com/accounts/new", the test will fail, despite the actual behavior is that at the url /accounts, the "new" is actually being rendered. – Brian Dear May 27 '13 at 16:54
0

If validation fails, user should see the form with the errors and stay at /posts/new. That's what you want, right?

There's a simple way to achieve this.

Set remote: true on the form to prevent the url from advancing. Handle ajax:success to replace the form on the page with the newly rendered one.

$('form[data-remote=true]').on 'ajax:success', (e, data, status, xhr) ->
  if isHTML(data)
    thisForm = "form[id=#{@getAttribute('id')}]"
    $(thisForm).replaceWith $(data).find(thisForm)

isHtml() function is from this question.

Community
  • 1
  • 1
Anton Khamets
  • 111
  • 1
  • 6