Ruby on Rails: How would i stay on the same page if the post is not saved?

20,170

Solution 1

flash.now with render is what you're looking for.

flash.now[:notice] = "Post can not be saved, please enter information."
render :new

Also instead of

flash[:notice] = "Post has been saved successfully."
redirect_to posts_path

you can just write

redirect_to posts_path, :notice => "Post has been saved successfully."

and it will do the same thing. It works only with redirect_to though, not with render!

Solution 2

Something like this should do what you want:

flash[:notice] = "Post can not be saved, please enter information."
render :new

UPDATE: You updated your question so I have to update my answer. Render is the right way to do this. However, it looks like you load some categories and some other collection of stuff in your new method. Those same instance variables should be available to your create method. The cleanest way to do this is put them into another method and have that method used as a before_filter applied to both create and new. Something like this:

before_filter :load_stuff, :only => [:create, :new]

def load_stuff
  @arr_select = { 1=>"One",2=>"Two" ,3=>"Three" }
  @categories_select = Category.all.collect {|c| [ c.category_name, c.id ] }
end

Then your new method is pretty much blank and calling render :new in your create method should work.

Solution 3

Hey this answer is super late but thought I'd add it for anyone that comes across it. Probably the most simple solution for what you want to achieve is to add required: true to all of the form inputs you want filled out. E.g

f.text_field :title, required: true, class: "whateverclassyouwant" 

This way the form will ONLY be submitted if these fields have been filled in correctly and if not an error flash message will pop up on the field that it needs to be completed. The default flash messages that pop up can be custom styled also, Google how to do so.

This way you can remove the else redirect all together in your create method as it will never get to that point, and just have the if save, flash success etc.

Share:
20,170
shibly
Author by

shibly

Updated on February 19, 2020

Comments

  • shibly
    shibly about 4 years
    def create
        @addpost = Post.new params[:data]
        if @addpost.save
            flash[:notice] = "Post has been saved successfully."
            redirect_to posts_path
        else
            flash[:notice] = "Post can not be saved, please enter information."
        end
    end
    

    If the post is not saved then it redirects to http://0.0.0.0:3000/posts , but i need to stay on the page, with text input fields so that user can input data.

    post model

    class Post < ActiveRecord::Base
    
        has_many :comments
        validates :title, :presence => true
        validates :content, :presence => true
        validates :category_id, :presence => true
        validates :tags, :presence => true
    end
    

    new method

    def new
        @arr_select = { 1=>"One",2=>"Two" ,3=>"Three" }
        @categories_select = Category.all.collect {|c| [ c.category_name, c.id ] }
    end
    

    new.html.erb

    <h3>Add post</h3>
    
    <%= form_tag :controller=>'posts', :action=>'create' do %>
        <%= label :q, :Title %>
        <%= text_field :data, :title, :class => :addtextsize %><br/>
        <%= label :q, :Content %>
        <%= text_area  :data, :content, :rows=>10 , :class => :addtextarea %><br/>
        <%= label :q, :Category %>
        <%= select :data, :category_id, @categories_select %><br/>
        <%= label :q, :Tags %>
        <%= text_field :data, :tags, :class => :addtextsize %><br/>
        <%= label :q, :Submit %>
        <%= submit_tag "Add Post" %>
    <% end %>
    

    What should i do ?

  • shibly
    shibly over 12 years
    Not render, rather i used this, redirect_to new_post_path, and it looks ok. With render i got error. NoMethodError in Posts#create Showing /path/to/app/views/posts/new.html.erb where line #10 raised: You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.map
  • shibly
    shibly over 12 years
    No, i want to stay in the same posts/new page. With render i got error. NoMethodError in Posts#create Showing /path/to/app/views/posts/new.html.erb where line #10 raised: You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.map, I have updated original post/question, see that again to understand.
  • Taryn East
    Taryn East over 12 years
    Ok, redirecting is bad because you lose the list of errors that are what the user needs to see to determine what went wrong with their new user. So... instead of redirecting so the bug goes away... lets actually fix the bug. :) can you provide the code at line 10 in new.html.erb
  • U-DON
    U-DON over 12 years
    Can you show your "new"? I think perhaps it is rendering the new.html.erb template, which contains (probably) a post variable or something. You may want to rename addpost to post if that is the case. Still, it's hard to say what the exact problem is without seeing your "new" function.
  • Taryn East
    Taryn East over 12 years
    redirect will lose the temporary @post variable which contains all the errors.
  • shibly
    shibly over 12 years
    I have updated the original post/question. See that again to understand.
  • Jakub Arnold
    Jakub Arnold over 12 years
    It looks like your new.html.erb template is using @post variable, which doesn't exist in the create method for the controller. Rename @addpost to just @post and it should work.
  • shibly
    shibly over 12 years
    Where did you get @post variable? post variable was not used in new.html.erb
  • Jakub Arnold
    Jakub Arnold over 12 years
    @guru Sorry didn't see the edit. You're using @categories_select which isn't available in the create method. render only renders the tempalte, it doesn't execute the controller action, so neither of those two instance methods get set.
  • shibly
    shibly over 12 years
    How can i make the @categories_select available to create method?
  • Jakub Arnold
    Jakub Arnold over 12 years
    @guru you're going to have to duplicate the code ... copy it from the new method.
  • shibly
    shibly over 12 years
    Yes, i copied this line, @categories_select = Category.all.collect {|c| [ c.category_name, c.id ] } to create method and no error now with render :new, but the result of render :new and redirect_to new_post_path are similar page with blank input textboxes.
  • Carl Zulauf
    Carl Zulauf over 12 years
    My answer is still the correct way. Updated to hopefully make why more clear.
  • Jakub Arnold
    Jakub Arnold over 12 years