Dmitriy K.
Dmitriy K.

Reputation: 23

Rails: Edit Comment without redirecting to the Edit View

I'm building simple web app where people can share their thought / pictures / so on. It has just two controllers Post, and nested in it Comments. Generally, at the moment all works perfectly, users can add, edit and delete posts the same way as comments. The thing I'm trying to do, and have big troubles with, is possibility to Edit comments without redirecting to the Edit Comment View - so to be able to do it from the "posts#show" level, the same way as comments actually are being created. I think it just would look much more nicer... Here are my:

posts_controller.rb

class PostsController < ApplicationController

before_action :find_post, only: [:show, :edit, :update, :destroy]

def index
    @posts = Post.all.order(created_at: :desc)
end

def new
    @post = Post.new
end

def create
    @post = Post.new(post_params)
    if @post.save
        redirect_to @post
    else
        render 'new'
    end
end

def show
    @comments = @post.comments
end

def edit
end

def update
    if @post.update(post_params)
        redirect_to @post
    else
        render 'edit'
    end
end

def destroy
    @post.destroy
    redirect_to root_path
end

private
def find_post
    @post = Post.find(params[:id])
end

def post_params
    params.require(:post).permit(:title, :description)
end
end

comments_controller.rb

class CommentsController < ApplicationController

before_action :find_post, only: [:create, :edit, :update, :destroy]

def create
    @comment = @post.comments.create(comment_params)
    if @comment.save
        redirect_to @post
    else
        render 'new'
    end
end

def edit
    @comment = @post.comments.find(params[:id])
end

def update
    @comment = @post.comments.find(params[:id])
    @comment.update_attributes(comment_params)
    if @comment.save
        redirect_to @post
    else
        render 'edit'
    end
end

def destroy
    @comment = @post.comments.find(params[:id])
    @comment.destroy
    redirect_to @post
end

private
def find_post
    @post = Post.find(params[:post_id])
end

def comment_params
    params.require(:comment).permit(:content)
end
end

View show.html.haml - for post

%h1 Show page
%h3= @post.title
%p= @post.description
=link_to "Edit memory", edit_post_path
=link_to "Delete memory", post_path, method: :delete

%h4 Share your thoughts about the memory

- @comments.each do |comment|
    %p= comment.content
    =link_to "Edit thought", edit_post_comment_path(@post, comment)
    =link_to "Delete thought", post_comment_path(@post, comment), method: :delete

= simple_form_for([@post, @post.comments.build]) do |c|
    = c.input :content
    = c.submit "Share thought"

View edit.html.haml - for comments (the one I'd like to get rid of / nest somehow to the view shown above)

= simple_form_for([@post, @comment]) do |c|
    = c.input :content
    = c.submit "Update thought"

I believe there is a simple solution, however despite the fact that I've been reading a lot about possible solution, for a newbie like me it's still difficult to figure out how this should be programed.

Upvotes: 2

Views: 1062

Answers (1)

Richard Peck
Richard Peck

Reputation: 76784

The terminology you're looking for is in-place editing, or inline editing

You'll either need a form or JQuery plugin to make any comment written by current_user (assuming you're using Devise) editable.

I've done this a little (you can sign up for free here, click "profile" and then edit the description):

enter image description here

--

The way you'd want to do it is something like this:

#app/assets/javascripts/application.js
# include x-editable scripts
$(".editable).editable([..options..]);

#app/views/posts/index.html.erb
<% @posts.each do |post| %>
   <%= post.body %>
   <% post.comments.each do |comment| %>
      <% if comment.author == current_user %>
         <%= content_tag :div, comment.body, class: "editable" %>
      <% end %>
   <% end %>
<% end %>

I've forgotten how we implemented the provided example; x-editable seems to be the rage now.

Here's how it works:

  • Include X-Editable (or other plugin) in your app
  • X-Editable will check for the presence of a .class or #id on an element
  • Providing such an element will allow X-Editable to make it editable
  • X-Editable then sends the completed request to the server, acting as Ajax

Looks like there's an x-editable-rails gem you can use:

#Gemfile
gem `x-editable-rails`

#app/assets/javascripts/application.js
#= require editable/bootstrap-editable
#= require editable/rails 

#app/views/posts/index.html.erb
<% @posts.each do |post| %>
   <% post.comments.each do |comment| %>
      <%= editable comment, :body if comment.author == current_user %>
   <% end %>
<% end %>

Upvotes: 1

Related Questions