1

I'm having trouble getting my redirect and error messages to work. From what I've read you cant get a forms errors to show up when you use redirect so I am trying to use render after it fails.

I have a new post form on a topic page. The url is "topic/1". If you make a post about the topic and something is wrong with the input I want it to go back to the page at topic/1 and display errors and I cant figure out how to get it to go back. Redirect (:back) does what I want but doesnt show the forms errors.

The form on the topic's show.html page:

<%= form_for(@post) do |f| %>
<%= render 'shared/post_error_messages' %>

<%= f.label :title, "Post Title" %>
<%= f.text_field :title %>

<%= f.label :content %>
<%= f.text_field :content %>

<%= f.hidden_field :parent_id, value: 0 %>
<%= f.hidden_field :topic_id, value: @topic.id %>
<%= f.hidden_field :user_id, value: current_user.id %>

<%= f.submit "Create Post" , class: "btn btn-small btn-primary" %>
<% end %>

Create action in the Posts controller

def create

    @post = Post.new(post_params)
    @topic = Topic.find_by(id: params[:topic_id])
    if @post.save
    redirect_to @post
else

    @topic = Topic.new
    render "/topics/show"  
end
end

I guess I'm mostly trying to do the render with the id from the page that the form was originally on.

Matthew
  • 432
  • 4
  • 17
  • You have to tell the method what to render. In this case I'm guessing it is the `:new` template. – Omni Jul 14 '14 at 02:42
  • I left out what I had because it didn't work and I was trying a bunch of different ideas, I edited my original post with what I have now. It shows the errors messages and the form but I cant get it show the rest of the page which is the list of posts associated with that topic id. – Matthew Jul 14 '14 at 02:46
  • `@topic = Topic.new` in create not necessary just use `render 'new'` – Nithin Jul 14 '14 at 04:47

2 Answers2

1

Errors

The problem isn't anything to do with the way you're rendering the form (render or redirect) - it's to do with the way you're handling your ActiveRecord object.

When you use form_for, Rails will append any errors into the @active_record_object.errors method. This will allow you to call the following:

form_for error messages in Ruby on Rails

<%= form_for @object do |f| %>
  <% @location.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
   <% end %>
<% end %>

This only works if you correctly create your ActiveRecord object, which you seem to do

--

Nested

#config/routes.rb
resources :topics do 
   resources :posts, path: "", path_names: {new: ""}, except: [:index] #-> domain.com/topics/1
end

You'll be much better using the following setup for a nested route:

<%= form_for [@topic, @post] do |f| %>
   ...
<% end %>

This allows you to create a form which will route to the topics_posts_path, which is basically what you need. The controller will then balance that by using the following:

#app/controllers/topics_controller.rb
Class TopicsController < ApplicationController
   def new
       @topic = Topic.find params[:topic_id]
       @post = Post.new
   end
   def create
       @topic = Topic.find params[:topic_id]
       @post = Post.new post_params
   end

   private

   def post_params
      params.require(:post).permit(:attributes)
   end 
end
Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • This got me on the right track I think. I took out the path: path_names expect part. It was giving me an error about the view not being there. i think its because I'm using the show view for topics and new in posts for making a new post. But everything seems to be working the way I want it too. Redirect and urls are all correct. – Matthew Jul 14 '14 at 19:34
0

You are overwriting the Topic you original found with a brand new, empty one - which shouldn't be necessary and which is causing the posts related to it to disappear.

Also - if your topic and post are related - you should create the post on the appropriate association @topic.posts instead of the main Post class.

The @topic.posts.new means that the post's topic-id is automatically updated with the value of the @topic.id ... which means you don't need to set it in the hidden-field on the form. In fact it's better if you don't - just delete that hidden field entirely.

If you add that to the first time you get a new post too (eg in topics/show) then you won't need to pass in a value to the hidden-field.

Also I'd do the same for all the other hidden-fields on the server-side too. You don't really want the user to use firebug to hack the form and add some other user's id... so do it in the create action and don't bother with the hidden field

This should work:

def create    
    @topic = Topic.find_by(id: params[:topic_id])

    @post = @topic.posts.new(post_params)
    @post.user = current_user
    @post.parent_id = 0

    if @post.save
        redirect_to @post
    else
        render "/topics/show"  
    end
end

if it doesn't - let me know what error messages you get (so we can debug)

Taryn East
  • 27,486
  • 9
  • 86
  • 108
  • 1
    The other post with the nested routes helped. Thanks for the tip about the hidden fields though and create with the relationship. I didnt think of that. – Matthew Jul 14 '14 at 19:45