Skip to main content

How can I solve it?

General • Asked by Federico Calarco

Hello guys I have a problem with this!

I'm making my website where user can give feedback to my projects, contact me and make comment to a blog_post.
The problem is when i make the render 'blog_posts/form' the errors are
"First argument in form cannot contain nil or be empty" - (@blog_post) ( solvable with -BlogPost.new-)
the second error after that is
"undefined method `errors' for nil:NilClass" - <% if @blog_post.errors.any? %>

If i remove the block with the if statement for errors everything will work but there will be no parsing error after the create/new action (I set up the validations of the presence of name and content in the model )
I'm waiting for your help , thank you


<div class="col-sm-6 col-sm-offset-3"  >
  <div class="modal fade " id="myModal" tabindex="-1" role="dialog">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
          <h4 class="modal-title">Modal title</h4>
          <%= form_for(BlogPost.new) do |f| %>
            <% if @blog_post.errors.any? %>
              <div id="error_explanation">
                <h2><%= pluralize(@blog_post.errors.count, "error") %> prohibited this blog_post from being saved:</h2>

                <ul>
                <% @blog_post.errors.full_messages.each do |message| %>
                  <li><%= message %></li>
                                        <div class="col-sm-2  pull-left" id="socialize">
                                <p>I'm a social persons find me :<br>fb tw insta</p>

                                        </div>

                <% end %>
                </ul>
              </div>
            <% end %>

            <div class="field">
              <%= f.label :title %><br>
              <%= f.text_field :title %>
            </div>
            <div class="field">
              <%= f.label :description %><br>
              <%= f.text_area :description %>
            </div>
            <div class="field">
              <%= f.label :status %><br>
              <%= f.check_box :status %>
            </div>
            <div class="field">
              <%= f.label :category %><br>
              <%= f.text_field :category %>
            </div>
            <div class="field">
              <%= f.label :post_date %><br>
              <%= f.date_select :post_date %>
            </div>
            <div class="actions">
              <%= f.submit %>
            </div>
          <% end %>

        </div>
        <div class="modal-body">
        <div class="modal-footer">
          <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
          <button type="button" class="btn btn-primary">Save changes</button>
        </div>
      </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
  </div><!-- /.modal -->
</div>


            </div>

I tried to copy and past the code block but it doesn't work


For code blocks, you can write backticks ` around your content so that it shows up as code and doesn't get eaten. :)

```
code
```

Sounds like you just need to set your @blog_post variable in your controller action. Have you set that? You'll also need to modify your form_for to be form_for(@blog_post) to be consistent.

@blog_post = BlogPost.new


I thought the same thing and I immediately wrote the code in the controllers but it still does not work , I really don't know where is my error


What does your controller look like?


class BlogPostsController < ApplicationController
  before_action :set_blog_post, only: [:show, :edit, :update, :destroy]



  # GET /blog_posts
  # GET /blog_posts.json
  def index
    @blog_posts = BlogPost.all

  end

  # GET /blog_posts/1
  # GET /blog_posts/1.json
  def show
  end

  # GET /blog_posts/new
  def new
    @blog_post = current_admin.blog_posts.new
  end

  # GET /blog_posts/1/edit
  def edit
  end

  # POST /blog_posts
  # POST /blog_posts.json
  def create

    @blog_post = current_admin.blog_posts.new(blog_post_params)

    respond_to do |format|
      if @blog_post.save
        format.html { redirect_to @blog_post, notice: 'Blog post was successfully created.' }
        format.json { render :show, status: :created, location: @blog_post }
      else
        format.html { render :new }
        format.json { render json: @blog_post.errors, status: :unprocessable_entity }
      end
    end

  end

  # PATCH/PUT /blog_posts/1
  # PATCH/PUT /blog_posts/1.json
  def update
    respond_to do |format|
      if @blog_post.update(blog_post_params)
        format.html { redirect_to @blog_post, notice: 'Blog post was successfully updated.' }
        format.json { render :show, status: :ok, location: @blog_post }
      else
        format.html { render :edit }
        format.json { render json: @blog_post.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /blog_posts/1
  # DELETE /blog_posts/1.json
  def destroy
    @blog_post.destroy
    respond_to do |format|
      format.html { redirect_to blog_posts_url, notice: 'Blog post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_blog_post
      @blog_post = BlogPost.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def blog_post_params
      params.require(:blog_post).permit(:title, :description, :status, :category, :post_date)
    end
end

The render ( of the form ) is inside a modal in /layouts/application.html.erb
Should I declare the variable in other controller?


Ah! So if you've got it on the application layout, that means you need to set the @blog_post variable on every page. You've got two approaches for this.

  1. You can create a before_action :set_blog_post on ApplicationController so it runs on every action.
  2. Or I realized you could modify your form like this (I'd recommend this approach in this case):
          <%= form_for(BlogPost.new) do |f| %>
            <% if f.object.errors.any? %>
              <div id="error_explanation">
                <h2><%= pluralize(@f.object.errors.count, "error") %> prohibited this post from being saved:</h2>

                <ul>
                <% f.object.errors.full_messages.each do |message| %>
                  <li><%= message %></li>
                                        <div class="col-sm-2  pull-left" id="socialize">
                                <p>I'm a social persons find me :<br>fb tw insta</p>

                                        </div>

                <% end %>
                </ul>
              </div>
            <% end %>

            <div class="field">
              <%= f.label :title %><br>
              <%= f.text_field :title %>
            </div>
            <div class="field">
              <%= f.label :description %><br>
              <%= f.text_area :description %>
            </div>
            <div class="field">
              <%= f.label :status %><br>
              <%= f.check_box :status %>
            </div>
            <div class="field">
              <%= f.label :category %><br>
              <%= f.text_field :category %>
            </div>
            <div class="field">
              <%= f.label :post_date %><br>
              <%= f.date_select :post_date %>
            </div>
            <div class="actions">
              <%= f.submit %>
            </div>
          <% end %>

What I did here was change @blog_post to f.object which is a reference to the BlogPost.new that you passed into the form_for originally. This way you won't need the @blog_post variable at all.


OOOOOOK , it works , but now if I write an empty blog_post there are no error like " title can't be blank" , it's a half success :D


Yeah, when you use BlogPost.new, that's creating a new object without errors, so those obviously won't exist on a new one.

One solution is to go in your app/views/blog_posts/new.html.erb you'll want to make sure you use @blog_post so that it has the errors when it renders. This way it will try to save, when it fails, it will render blog_posts/new and you'll have the errors on the @blog_post object that you can render.

The other alternative would be to submit the form with JS and use that to display the errors.


Perfect , I will search how to do that, thank you!


Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 27,623+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.