Home > Software engineering >  Rails: Adding a post without refreshing the page
Rails: Adding a post without refreshing the page

Time:09-28

I'm new on ruby on rails.

I'm currently working on a facebook clone application and having trouble when adding a post without refreshing the page. Tried to create a post but the post did not show upon submitting and encountered Internal Server Error. When the page is refreshed, the newly created post is finally displayed.

Error in rails server

Completed 500 Internal Server Error in 50ms (ActiveRecord: 15.9ms | Allocations: 10085)



ActionView::Template::Error (First argument in form cannot contain nil or be empty):
    1: = form_for([post, @comment]) do |f|
    2:   .form-bottom-button-container
    3:     .d-flex.comment-text-button
    4:       .p-2.flex-grow-1

Here are my codes. Please help me out. Thank you very much!

app/controllers/posts_controller.rb

def create
  @post = current_user.posts.build(post_params)
  respond_to do |format|
    if @post.save
      format.js
      format.html { redirect_to posts_path, notice: 'Successfully posted.'}
    else
      format.html { redirect_to posts_path, status: :unprocessable_entity }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

app/views/posts/create.js.haml

:plain
  $("#post-display").append("#{escape_javascript(render 'post_display', post: @post)}");

app/views/posts/index.html.haml

-# All Posts
.col-8
  .post-form
    = render "post_form"
  - if @posts.empty?
    .post-card
      .post-text
        .no-post-text No posts to show
  - else
    #post-display
      = render partial: "post_display", collection: @posts, as: :post

app/views/posts/_post_display.html.haml

.post-card
  .post-text
    .d-flex.justify-content-between
      .d-flex
        .post-user-image
          - if post.user.profile_pic.present?
            = image_tag post.user.profile_pic.url, class: "img img-fluid img-thumb"
          - else
            = image_tag "/default-user.jpg", class: "img img-fluid img-thumb"
        .d-flex.flex-column
          .username-bold= link_to post.user.username, profile_path(post.user.username)
          .distance-date= distance_of_time_posted_in_words(post.created_at)
      .post-edit-delete
        - if post.user.username == current_user.username
          = link_to edit_post_path(post), class: "text-space", remote: true, "data-bs-toggle" => "modal", "data-bs-target" => "#edit-post-#{post.id}-modal" do
            %i.fa.fa-edit
          .modal.fade(id="edit-post-#{post.id}-modal" tabindex="-1" aria-labelledby="edit-post-title" aria-hidden="true")
            .modal-dialog.modal-dialog-centered.modal-dialog-scrollable
              .modal-content
          = link_to post, method: :delete, class: "text-space" do
            %i.fa.fa-trash
    .caption= post.caption
  - if post.image.present?
    = image_tag post.image.url, class: "img img-fluid img-fill"

  -# Like Button
  .row.container-margin-top
    .col-6
      - if liker(post)
        = button_to post_like_path(post, liker(post)), method: :delete, class: "btn btn-maroon btn-wide btn-like-comment" do
          %i.far.fa-thumbs-up
          Unlike
      - else
        = button_to post_likes_path(post), method: :post, class: "btn btn-plain btn-wide btn-like-comment" do
          %i.far.fa-thumbs-up
          Like
    .col-6
      .btn.btn-plain.btn-wide.btn-like-comment.btn-comment
        %i.far.fa-comment
        %span Comment

  -# Comment Section
  .comment-box
    .d-flex.justify-content-between
      - unless post.likes.count == 0
        .post-likes(type="button" data-bs-toggle="modal" data-bs-target="#likers-#{post.id}-modal")= "#{pluralize(post.likes.count, "like")}"
        = render "layouts/likers_modal", post: post, index: post.id
      .comment-toggle View Comments
    .comment-display.hidden
      = render "posts/comments", post: post
  .comment-form
    = render "comments/comment_form", post: post

app/views/comments/_comment_form.html.haml

= form_for([post, @comment]) do |f|
  .form-bottom-button-container
    .d-flex.comment-text-button
      .p-2.flex-grow-1
        = f.text_area :content, class: "comment-text-area comment", placeholder: "Write a comment..."
      .p-2
        = f.submit :Comment, class: "btn btn-maroon create-comment-button"

CodePudding user response:

Check your application logs - it'll probably tell you the format.js method does not exist.

def create
  @post = current_user.posts.build(post_params)
  respond_to do |format|
    if @post.save
      format.js # <----
      format.html { redirect_to posts_path, notice: 'Successfully posted.'}
    else
      format.html { redirect_to posts_path, status: :unprocessable_entity }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

Just remove that line or use the format.json method and you're good to go.

CodePudding user response:

To make the page not refresh you must submit the form using ajax request... you simply add remote: true to the form.

form_for([post, @comment], remote: true) do |f|

Also the error you are getting is because @comment is not being set.

  • Related