I am attempting to build a group chat system where members of the group are able to leave comments in the group's chat section. I am using Actioncable with Rails 5 to implement this in real time, but am unable to overcome a particular hurdle. Chat comments are posted to the database as usual, but there is an error somewhere with the rendering and real-time functionality. Below are all of the affiliated code samples and the error from my terminal. I have been working on this for ages. I am in dire need of enlightenment.
The error: (The entire error message is very long, but this is where the error begins.)
Finished "/cable/" [WebSocket] for 127.0.0.1 at 2018-06-25 18:11:13 -0500
GroupChatCommentsChannel stopped streaming from group:5:group_chat_comments
Started GET "/cable" for 127.0.0.1 at 2018-06-25 18:11:13 -0500
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-06-25 18:11:13 -0500
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket)
GroupChatCommentsChannel is transmitting the subscription confirmation
GroupChatCommentsChannel#follow({"group_id"=>5})
GroupChatCommentsChannel is streaming from group:5:group_chat_comments
Started POST "/groups/5/group_chat_comments" for 127.0.0.1 at 2018-06-25 18:11:50 -0500
Processing by GroupChatCommentsController#create as JS
Parameters: {"utf8"=>"✓", "group_chat_comment"=>{"body"=>"2"}, "commit"=>"Comment", "group_id"=>"5"}
Group Load (0.4ms) SELECT `groups`.* FROM `groups` WHERE `groups`.`id` = 5 LIMIT 1
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
(0.2ms) BEGIN
Group Load (0.3ms) SELECT `groups`.* FROM `groups` WHERE `groups`.`id` = 5 LIMIT 1
SQL (5.8ms) INSERT INTO `group_chat_comments` (`body`, `user_id`, `group_id`, `created_at`, `updated_at`) VALUES ('2', 1, 5, '2018-06-25 23:11:50', '2018-06-25 23:11:50')
(7.2ms) COMMIT
[ActiveJob] Enqueued RenderGroupChatCommentJob (Job ID: ddceb77d-7c5c-42a3-8570-55d09a569c9e) to Async(default) with arguments: #<GlobalID:0x007f87af0ff7d8 #uri=#<URI::GID gid://news/GroupChatComment/4>>
Rendering group_chat_comments/create.js.erb
Rendered group_chat_comments/_new.html.erb (1.8ms)
Rendered group_chat_comments/create.js.erb (31.6ms)
Completed 200 OK in 201ms (Views: 75.1ms | ActiveRecord: 36.5ms)
GroupChatComment Load (0.2ms) SELECT `group_chat_comments`.* FROM `group_chat_comments` WHERE `group_chat_comments`.`id` = 4 LIMIT 1
[ActiveJob] [RenderGroupChatCommentJob] [ddceb77d-7c5c-42a3-8570-55d09a569c9e] Performing RenderGroupChatCommentJob (Job ID: ddceb77d-7c5c-42a3-8570-55d09a569c9e) from Async(default) with arguments: #<GlobalID:0x007f87ab6a1960 #uri=#<URI::GID gid://news/GroupChatComment/4>>
[ActiveJob] [RenderGroupChatCommentJob] [ddceb77d-7c5c-42a3-8570-55d09a569c9e] Rendered group_chat_comments/_group_chat_comment.html.erb (26.1ms)
[ActiveJob] [RenderGroupChatCommentJob] [ddceb77d-7c5c-42a3-8570-55d09a569c9e] Error performing RenderGroupChatCommentJob (Job ID: ddceb77d-7c5c-42a3-8570-55d09a569c9e) from Async(default) in 60.85ms: ActionView::Template::Error (No route matches {:action=>"show", :controller=>"group_chat_comments", :group_id=>nil, :id=>"4"}, missing required keys: [:group_id]):
The code:
Routes:
resources :groups do
resources :group_chat_comments
end
mount ActionCable.server => '/cable'
Model:
class GroupChatComment < ApplicationRecord
belongs_to :user
belongs_to :group
after_create_commit { RenderGroupChatCommentJob.perform_later self }
end
Controller:
class GroupChatCommentsController < ApplicationController
before_action :set_group
before_action :authenticate_user!
def create
#group_chat_comment = GroupChatComment.create! body: params[:group_chat_comment][:body], group_id: #group.id, user: current_user
end
def destroy
#group_chat_comment = GroupChatComment.find(params[:id])
#group_chat_comment.destroy
redirect_to #group
end
private
def set_group
#group = Group.find(params[:group_id])
end
end
Job:
class RenderGroupChatCommentJob < ApplicationJob
queue_as :default
def perform(group_chat_comment)
ActionCable.server.broadcast "group:#{group_chat_comment.group_id}:group_chat_comments", foo: render_group_chat_comment(group_chat_comment)
end
private
def render_group_chat_comment(group_chat_comment)
ApplicationController.renderer.render(partial: 'group_chat_comments/group_chat_comment', locals: { group_chat_comment: group_chat_comment })
end
end
Channel:
class GroupChatCommentsChannel < ApplicationCable::Channel
def follow(params)
stop_all_streams
stream_from "group:#{params['group_id'].to_i}:group_chat_comments"
end
def unfollow
stop_all_streams
end
end
Channel CoffeeScript:
App.group_chat_comments = App.cable.subscriptions.create "GroupChatCommentsChannel",
collection: -> $('#group_chat_comments')
connected: ->
setTimeout =>
#followCurrentGroup()
, 1000
disconnected: ->
followCurrentGroup: ->
groupId = #collection().data('group-id')
if groupId
#perform 'follow', group_id: groupId
else
#perform 'unfollow'
received: (data) ->
#collection().append(data['group_chat_comment'])
Cable.js:
//= require action_cable
//= require_self
//= require_tree ./channels
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);
The views:
Create.js:
$('#new_group_chat_comment').replaceWith('<%=j render 'group_chat_comments/new', group: #group %>');
_group_chat_comment partial:
<% cache group_chat_comment do %>
<div class="group_chat_comment">
<p>
<%= group_chat_comment.body %>
<%= link_to 'Delete', group_group_chat_comment_path(#group, group_chat_comment), method: :delete %>
</p>
</div>
<% end %>
_group_chat_comments partial:
<%= render 'group_chat_comments/new', group: #group %>
<section id="group_chat_comments" data-group-id="<%= #group.id %>">
<%= render #group.group_chat_comments %>
</section>
_new partial:
<%= form_for [ #group, GroupChatComment.new ], remote: true do |f| %>
<div class="group-comment">
<%= f.text_area :body %>
</div>
<br>
<div class="group-comment-submit">
<%= f.submit 'Comment' %>
</div>
<% end %>
Related
Turbo is slow on JavaScript side that I am forced to delay Ruby side. If I don't delay the server response, there are no turbo stream updates on the page. My logs show every turbo stream is rendering and all the jobs get executed and transmitted.
Controller:
# app/controllers/grids_controller.rb
class GridsController < ApplicationController
def play
#job_id = PlayJob.perform_later(**#grid_data.attributes).job_id # Turbo broadcasts
render :play, status: :created
end
end
Turbo stream view:
<!-- app/views/grids/play.html.erb -->
<%= turbo_stream_from :play, #job_id %>
<div id="grid">
<% unless Rails.env.test? %>
<p><strong>Phase 0</strong></p>
<div class="cells">
<%= image_tag asset_url('loading.gif'), alt: 'loading', class: 'loading' %>
</div>
<% end %>
</div>
Turbo broadcasts:
# lib/grid.rb
class Grid
def play(job_id)
sleep 1 # I am forced to add delay of one second to get turbo to respond!
loop do
broadcast_to :play, job_id
break if phase >= #phases
sleep #phase_duration
next_phase
end
end
def broadcast_to(*streamable)
Turbo::StreamsChannel.broadcast_update_to(
streamable,
target: 'grid',
partial: 'grids/grid',
locals: { grid: self }
)
end
end
Here is the code of all my app: https://github.com/chiaraani/life-game-web
In your play action you're broadcasting to a channel that you haven't connected yet, then you're rendering play.html.erb where turbo_stream_from connects. By that time all the jobs have finished, which is why when you add delay there is time to connect and see updates.
You can also see it in the logs, all the jobs get done and then you see:
# jobs
# jobs
Turbo::StreamsChannel is streaming from ...
but there is nothing left to stream.
You have to have turbo_stream_from already connected before you submit the form and have #grid target already on the page ready to catch:
# app/views/new.html.erb
# NOTE: you can create Play model in `new` action and just do update.
# this way you have an `id` to broadcast to. I just made a random one
# in place.
<%= turbo_stream_from :play, (play_id = SecureRandom.uuid) %>
<%= form_with model: #grid_data, url: play_path, builder: GridFormBuilder do |f| %>
# send `id` back to controller
<%= hidden_field_tag :id, play_id %>
<% GridData.attribute_names.each do |attribute| %>
# just use `scope`
<%= f.label attribute, t(attribute, scope: :questions) %>
<%= f.number_field attribute %>
<% end %>
<%= f.submit %>
<% end %>
<%= tag.div id: "grid" %>
# app/controllers/grids_controller.rb
def create
#grid_data = GridData.new(**grid_params)
respond_to do |format|
if #grid_data.valid?
# pass `id` so we can broadcast to it
#grid_data.to_grid.play(params[:id])
# it just needs to be an empty response, but it has to be `turbo_stream`
format.turbo_stream { render inline: "" }
else
format.html { render :new, status: :unprocessable_entity }
end
end
end
You can remove all sleep delays and see how fast it is.
I was trying to work through Section 5 of Working with JavaScript in Rails http://guides.rubyonrails.org/working_with_javascript_in_rails.html .
Issue I have is that the new user isn't displayed in the show page until a refresh the entire page. I think I've replicated all the code correctly, but can't see what's wrong.
users_controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#users = User.all
#user = User.new
end
...
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.js
format.json { render json: #user, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
user/index.html.erb
<b>Users</b>
<ul id="users">
<%= render #users %>
</ul>
<br>
<%= form_with(model: #user) do |f| %>
<%= f.label :name %><br>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
user/create.js.erb
$("<%= escape_javascript(render #user) %>").appendTo("#users");
logs
started POST "/users" for 127.0.0.1 at 2018-03-30 17:23:36 +0100
Processing by UsersController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"xMBe+h9zi5rWE8JXltYw1fGwQUP8AL2iWaaaGVqwbPvYavJgv7eQ0J5hwRL9xkb2S0pnose3X6oo+YXywvlcaQ==", "user"=>{"name"=>"Dave"}, "commit"=>"Create User"}
(0.2ms) BEGIN
SQL (0.7ms) INSERT INTO "users" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["name", "Dave"], ["created_at", "2018-03-30 16:23:36.474360"], ["updated_at", "2018-03-30 16:23:36.474360"]]
(6.3ms) COMMIT
Rendering users/create.js.erb
Rendered users/_user.html.erb (0.3ms)
Rendered users/create.js.erb (3.7ms)
Completed 200 OK in 28ms (Views: 13.6ms | ActiveRecord: 7.3ms)
Started GET "/users" for 127.0.0.1 at 2018-03-30 17:23:38 +0100
Processing by UsersController#index as HTML
Rendering users/index.html.erb within layouts/application
User Load (0.3ms) SELECT "users".* FROM "users"
Rendered collection of users/_user.html.erb [3 times] (0.4ms)
Rendered users/index.html.erb within layouts/application (5.4ms)
Completed 200 OK in 54ms (Views: 49.7ms | ActiveRecord: 0.3ms)
I'm implementing comments as a nested resource for an events app and hitting one issue after another. Initially it worked fine, however, the only functionality they had was create & destroy. I want to add an edit function using Ajax/remote: true for same page editing (never done it before) and I've hit a wall. The edit link_to doesn't/has never worked and now even the create function doesn't work. This is what's coming through on the development log -
Processing by CommentsController#create as JS
Parameters: {"utf8"=>"✓", "comment"=>{"body"=>"Comment."}, "commit"=>"Create Comment", "event_id"=>"27"}
[1m[36mComment Load (0.1ms)[0m [1m[34mSELECT "comments".* FROM "comments" WHERE "comments"."id" = ? LIMIT ?[0m [["id", nil], ["LIMIT", 1]]
Completed 404 Not Found in 1ms (ActiveRecord: 0.1ms)
ActiveRecord::RecordNotFound (Couldn't find Comment with 'id'=):
I've tried all sorts of different parameters via trial and error but the 'id' issue keeps springing up. Here's my code -
comments_controller.rb
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :create, :edit, :update, :destroy]
def create
#event = Event.find(params[:event_id])
#comment = #event.comments.create(comment_params)
#comment.user_id = current_user.id
if #comment.save
redirect_to #event
else
render 'new'
end
end
# GET /comments/1/edit
def edit
#event = #comment.event
#comment = #event.comments.find(params[:id])
respond_to do |f|
f.js
f.html
end
end
def show
end
def update
if #comment.update(comment_params)
redirect_to #event, notice: "Comment was successfully updated!"
else
render 'edit'
end
end
def destroy
#event = Event.find(params[:event_id])
#comment = #event.comments.find(params[:id])
#comment.destroy
redirect_to event_path(#event)
end
private
def set_comment
#comment = Comment.find(params[:id])
end
def set_event
#event = Event.find(params[:event_id])
end
def comment_params
params.require(:comment).permit(:name, :body)
end
end
_comment.html.erb
<div class="comment clearfix">
<div class="comment_content">
<div id="<%=dom_id(comment)%>" class="comment">
<p class="comment_name"><strong><%= comment.name %></strong></p>
<p class="comment_body"><%= comment.body %></p>
</div>
<p><%= link_to 'Edit', edit_event_comment_path([comment.event, comment]), id: "comment", remote: true %></p>
<p><%= link_to 'Delete', [comment.event, comment],
method: :delete,
class: "button",
data: { confirm: 'Are you sure?' } %></p>
</div>
</div>
_form.html.erb
<%= simple_form_for([#event, #comment], remote: true) do |f| %>
<%= f.label :comment %><br>
<%= f.text_area :body %><br>
<br>
<%= f.button :submit, label: 'Add Comment', class: "btn btn-primary" %>
<% end %>
edit.js.erb
$('#comment').append('<%= j render 'form' %>');
I think I'm getting mixed up with the 'id's for this thing and how to get the remote: true function working on the page. I don't want to accept defeat but I may have to if I don't get this working.
UPDATE -
When I try and edit an existing comment I get this in my development log -
Started GET "/events/27%2F32/comments/27/edit" for ::1 at 2017-05-24 12:28:20 +0100
Processing by CommentsController#edit as JS
Parameters: {"event_id"=>"27/32", "id"=>"27"}
[1m[36mComment Load (0.1ms)[0m [1m[34mSELECT "comments".* FROM "comments" WHERE "comments"."id" = ? LIMIT ?[0m [["id", 27], ["LIMIT", 1]]
Completed 404 Not Found in 1ms (ActiveRecord: 0.1ms)
ActiveRecord::RecordNotFound (Couldn't find Comment with 'id'=27):
The route doesn't make sense - "/events/27%2F32/comments/27/edit" - the comment id should be 32 and the event id 27.
routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { omniauth_callbacks: "omniauth_callbacks", registrations: "registrations" }
resources :users
# the above resource draws out routes for user profiles
resources :events do
resources :comments
resources :bookings
end
root 'events#index'
change
before_action :set_comment, only: [:show, :create, :edit, :update, :destroy]
to
before_action :set_comment, only: [:show, :edit, :update, :destroy]
you can't set comment when you are creating it.
Also, as discussed in the comments, your edit link should be,
<%= link_to 'Edit', [comment.event, comment], id: "comment", remote: true %>
I'm trying to setup Dropzone in my Rails app to upload multiple images. Dropzone seems to appear on the page fine, but when I submit, the correct url is not uploaded to the database. The JSON returns {"message":"success","fileID":"/images/original/missing.png"}. It's using Paperclip's missing image url.
Picture Model
class Picture < ActiveRecord::Base
belongs_to :album
has_attached_file :image,
:path => ":rails_root/public/images/:id/:filename",
:url => "/images/:id/:filename",
:styles => { :small => "160x160>" }
do_not_validate_attachment_file_type :image
end
Pictures Controller
def create
#picture = Picture.create(picture_params)
if #picture.save
# send success header
render json: { message: "success", fileID: #picture.image.url }, :status => 200
else
# you need to send an error header, otherwise Dropzone
# will not interpret the response as an error:
render json: { error: #picture.errors.full_messages.join(',')}, :status => 400
end
end
pictures.js
$(document).ready(function(){
// disable auto discover
Dropzone.autoDiscover = false;
// grap our upload form by its id
$("#new_picture").dropzone({
// restrict image size to a maximum 1MB
maxFilesize: 1,
// changed the passed param to one accepted by
// our rails app
paramName: "picture[image]",
// show remove links on each image upload
addRemoveLinks: true
});
});
pictures/_form
<%= simple_form_for(#picture, :html => {:class => 'dropzone', multipart: true}) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :title %>
<%= f.input :description %>
<%= f.input :album_id %>
</div>
<%= f.label :pictures, :class => 'control-label' %>
<div class="controls">
<%= f.file_field "images[]"%>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Logs
Started POST "/pictures" for ::1 at 2015-01-03 21:49:10 -0500
Value for params[:picture][:images] was set to nil, because it was one of [], [null] or [null, null, ...]. Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation for more information.
Processing by PicturesController#create as JSON
Parameters: {"utf8"=>"✓", "authenticity_token"=>"oM1TCKtz7RGVdJ20qmlYVMXfMuSFylQbRZPkMWlBir8=", "picture"=>{"title"=>"", "description"=>"", "album_id"=>"", "images"=>nil, "image"=>#<ActionDispatch::Http::UploadedFile:0x007ff7d953d7b0 #tempfile=#<Tempfile:/var/folders/_q/9phh0t7s2xnfx_qy82w59thm0000gn/T/RackMultipart20150103-50729-10fo75i>, #original_filename="Space.jpeg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"picture[image]\"; filename=\"Space.jpeg\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"Create Picture"}
Unpermitted parameters: images
Command :: file -b --mime '/var/folders/_q/9phh0t7s2xnfx_qy82w59thm0000gn/T/d511f8439ecde36647437fbba67a439420150103-50729-eoe314.jpeg'
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/_q/9phh0t7s2xnfx_qy82w59thm0000gn/T/d511f8439ecde36647437fbba67a439420150103-50729-1tu8uv1.jpeg[0]' 2>/dev/null
Command :: identify -format %m '/var/folders/_q/9phh0t7s2xnfx_qy82w59thm0000gn/T/d511f8439ecde36647437fbba67a439420150103-50729-1tu8uv1.jpeg[0]'
Command :: convert '/var/folders/_q/9phh0t7s2xnfx_qy82w59thm0000gn/T/d511f8439ecde36647437fbba67a439420150103-50729-1tu8uv1.jpeg[0]' -auto-orient -resize "160x160>" '/var/folders/_q/9phh0t7s2xnfx_qy82w59thm0000gn/T/d511f8439ecde36647437fbba67a439420150103-50729-1tu8uv120150103-50729-5ctpcf'
Command :: file -b --mime '/var/folders/_q/9phh0t7s2xnfx_qy82w59thm0000gn/T/d511f8439ecde36647437fbba67a439420150103-50729-1tu8uv120150103-50729-5ctpcf'
(0.3ms) BEGIN
Command :: file -b --mime '/var/folders/_q/9phh0t7s2xnfx_qy82w59thm0000gn/T/d511f8439ecde36647437fbba67a439420150103-50729-113dzu5.jpeg'
SQL (0.6ms) INSERT INTO "pictures" ("created_at", "description", "image_content_type", "image_file_name", "image_file_size", "image_updated_at", "title", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["created_at", "2015-01-04 02:49:10.698173"], ["description", ""], ["image_content_type", "image/jpeg"], ["image_file_name", "Space.jpeg"], ["image_file_size", 344179], ["image_updated_at", "2015-01-04 02:49:10.397270"], ["title", ""], ["updated_at", "2015-01-04 02:49:10.698173"]]
(16.6ms) COMMIT
(0.3ms) BEGIN
(0.3ms) COMMIT
Completed 200 OK in 359ms (Views: 0.2ms | ActiveRecord: 18.1ms)
I'm also not sure how to fix the error in the second line of the log, which I think might be the problem.
In your create method, replace:
fileID: #picture.image.url
with:
fileID: #picture.id
you will need fileID to be the id of the upload so you can append it in the js to the delete button of each image.
also do you have images: [] in strong params in your controller? because I believe it should just be :image, also if you do that then in your form replace:
<%= f.file_field "images[]"%>
with:
<%= f.file_field :image, multiple: true %>
In Your JavaScript File
$(document).ready(function()
{
Dropzone.autoDiscover = false;
$("#new_upload").dropzone({
// restrict image size to a maximum 1MB
maxFilesize: 10,
// changed the passed param to one accepted by
// our rails app
paramName: "upload[image]",
// show remove links on each image upload
addRemoveLinks: true,
// if the upload was successful
success: function(file, response){
// find the remove button link of the uploaded file and give it an id
// based of the fileID response from the server
$(file.previewTemplate).find('.dz-remove').attr('id', response.fileID);
// add the dz-success class (the green tick sign)
$(file.previewElement).addClass("dz-success");
}
});
});
in your new.html.erb file
<%= f.file_field :image %><br>
<%= f.submit "Upload" %>
in your controller
def create
#upload = Upload.create(upload_params)
if #upload.save
# send success header
render json: { message: "success", fileID: #upload.id }, :status => 200
else
# you need to send an error header, otherwise Dropzone
# will not interpret the response as an error:
render json: { error: #upload.errors.full_messages.join(',')}, :status => 400
end
end
I'm having some issues deleting my comments with Ajax. I think I'm close but not sure and would like some advice. Still getting used to jquery and such. I can remove the comment via ajax but not actually delete the record itself so maybe its a simple syntax issue.
destroy.js.erb
$('#remove_comment').remove();
I think I need to tag this with the comment ID but I'm having issues being as the comments are nested under the Pit model.
_comment.html.erb
<div class = "well", id = "remove_comment">
<p>
<%= comment.body %>
<p>posted by: <%= comment.user.name %></p>
<div class = "response">
<p class = "like-response">Was this response persuading to you?</p>
<%= link_to "Yes", pit_comment_like_path(#pit, comment), method: :put %>
<%= link_to "No", pit_comment_dislike_path(#pit, comment), method: :put %>
</div>
<div class = "response-convince">
<p class = "dislike-comment">
<%= comment.get_dislikes.size %> users found this response unpersuasive
</p>
<p class = "like-comment">
<%= comment.get_likes.size %> users found this response persuasive</p>
</p>
</div>
<p>
<%if comment.user == current_user %>
<%= link_to 'Destroy Comment', [#pit, comment],
method: :delete,
data: { confirm: 'Are you sure?' }, remote: true, class: "btn btn-default" %>
</p>
<% end %>
</div>
Comments Controller
def destroy
#pit = Pit.find(params[:pit_id])
#comment = #pit.comments.find(params[:id])
#comment.destroy
respond_to do |format|
format.html {redirect_to pit_path(#pit)}
format.js {}
end
Logs seem to be working properly
Started DELETE "/pits/398/comments/63" for 127.0.0.1 at 2014-09-11 12:31:08 -0500
Processing by CommentsController#destroy as JS
Parameters: {"pit_id"=>"398", "id"=>"63"}
Pit Load (0.1ms) SELECT "pits".* FROM "pits" WHERE "pits"."id" = ? LIMIT 1 [["id", 398]]
Comment Load (0.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."pit_id" = ? AND "comments"."id" = ? LIMIT 1 [["pit_id", 398], ["id", 63]]
(0.1ms) begin transaction
ActsAsVotable::Vote Load (0.1ms) SELECT "votes".* FROM "votes" WHERE "votes"."votable_id" = ? AND "votes"."votable_type" = ? [["votable_id", 63], ["votable_type", "Comment"]]
SQL (0.3ms) DELETE FROM "comments" WHERE "comments"."id" = ? [["id", 63]]
(3.0ms) commit transaction
Rendered comments/destroy.js.erb (0.5ms)
Completed 200 OK in 13ms (Views: 3.9ms | ActiveRecord: 3.7ms)
This is the associated markup I have in pits/show.html.erb
<h3>Responses</h3>
<div id = "comment_body">
<%= render #pit.comments %>
</div>
<%= render partial: "comments/form" %>
pit.rb
class Pit < ActiveRecord::Base
validates :topic, :author, :summary, presence: true
acts_as_votable
has_many :comments
belongs_to :user
mount_uploader :image, ImageUploader
end
comment.rb
class Comment < ActiveRecord::Base
acts_as_votable
belongs_to :pit
belongs_to :user
end
Everything inserts correctly with my create.js.erb. I just need to remove it and I think I need to pass in the comment ID or something to that effect. Any advice here would be appreciated. Thanks.
Actually, the comment is being DELETED as logs shows the query:
SQL (0.3ms) DELETE FROM "comments" WHERE "comments"."id" = ? [["id", 63]]
I guess your jQuery doesn't remove the appropriate comment after the callback. You can try changing view code of _comment.html.erb:
<div class = "well", id = "remove_comment_<%= comment.id %>">
<p>
<%= comment.body %>
And then your destroy.js.erb:
$("#remove_comment_<%= #comment.id %>").remove(); // Since #comment will be available in the variable here!
create a link_to with a data-id attribute, when clicked use jquery to make a GET request to your controller.
First, create a route for the delete action in your config/routes.rb:
get 'delete_comment' => 'comments#delete_comment'
Next, add a method to your controller (assumably CommentsController):
def delete_comment
#comment = Comment.find(params[:id])
#comment.destroy
end
Now, set up a link in your view:
= link_to "Remove Comment", "#", :class => "remove_comment", :'data-id' => #comment.id
Now set up the jquery GET request to fire when you click on the link:
$(".remove_comment").click(function(event){
event.preventDefault();
$.get("/delete_comment", {id: $(this).attr("data-id") } );
});
In this example, you would need to rename your delete.js.erb file to delete_comment.js.erb