I have a save_video action on my NodesController that does this:
format.html { redirect_to video_tag_users_path(#video) }
What I want to happen is when it calls that action, it should render my tag_users.js.erb, but it is not.
This is my tag_users action:
def tag_users
authorize! :read, #family_tree
#video = Video.find(params[:video_id])
#node = #video.node
respond_to do |format|
format.html
format.js
end
redirect_to root_path
end
This is the log of what is happening:
Redirected to http://localhost:3000/videos/164/tag_users
Completed 302 Found in 23ms (ActiveRecord: 12.3ms)
Started GET "/videos/164/tag_users" for 127.0.0.1 at 2015-03-20 08:24:09 -0500
Processing by VideosController#tag_users as HTML
Parameters: {"video_id"=>"164"}
# truncated for brevity
Rendered videos/tag_users.html.erb within layouts/application (0.2ms)
This is the file I want it to render: tag_users.js.erb
$("#add-video-step-3").html("<%= escape_javascript(render 'videos/tag_users_in_video') %>");
Which then renders this modal _tag_users_in_video.html.erb:
<div class="bootstrap-styles" id="add-video-step-5">
<div class="modal-header">
<div class="titles clearfix">
<h2>Tag Users</h2>
<p><i>Step 3 of 3</i></p>
</div>
</div>
<div class="modal-body">
<div class="content">
<div>Tag someone</div>
<%= simple_form_for #node, url: add_tagged_user_node_path(#node), method: :post do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.association :user, label: "Users", collection: #users, as: :check_boxes, checked: #node.user_tags %>
</div>
<div class="form-actions">
<%= f.button :submit, class: "btn btn-success ladda-button" %>
</div>
<% end %>
</div>
</div>
<div class="modal-footer">
</div>
</div>
Edit 1
So I changed the respond_to block in my tag_users action to this:
render 'tag_users.js'
But now it is actually rendering the JS rather than executing it and rendering the modal I want it to render.
i.e. this is what shows up in my browser, it redirects to URL localhost/videos/167/tag_users.js:
$("#add-video-step-3").html("<div class=\"bootstrap-styles\" id=\"add-video-step-5\"> \n <div class=\"modal-header\">\n <div class=\"titles clearfix\">\n <h2>Tag Users<\/h2>\n <p><i>Step 3 of 3<\/i><\/p>\n <\/div>\n <\/div>\n <div class=\"modal-body\">\n <div class=\"content\">\n <div>Tag someone<\/div>\n <form accept-charset=\"UTF-8\" action=\"/nodes/40/add_tagged_user\" class=\"simple_form edit_node\" id=\"edit_node_40\" method=\"post\" novalidate=\"novalidate\"><div style=\"display:none\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" /><input name=\"authenticity_token\" type=\"hidden\" value=\"Jj8CsHGzcNJJuJn9HGWjNaSjIfSJaZ8N81vmZ+Zp6KQ=\" /><\/div>\n \n \n <div class=\"form-inputs\">\n <div class=\"control-group check_boxes optional node_user\"><label class=\"check_boxes optional control-label\">Users<\/label><div class=\"controls\"><label class=\"checkbox\"><input class=\"check_boxes optional\" id=\"node_user_id_true\" name=\"node[user_id][]\" type=\"checkbox\" value=\"true\" />Yes<\/label><label class=\"checkbox\"><input class=\"check_boxes optional\" id=\"node_user_id_false\" name=\"node[user_id][]\" type=\"checkbox\" value=\"false\" />No<\/label><input name=\"node[user_id][]\" type=\"hidden\" value=\"\" /><\/div><\/div>\n <\/div> \n\n <div class=\"form-actions\">\n <input class=\"btn btn btn-success ladda-button\" name=\"commit\" type=\"submit\" value=\"Update Node\" />\n <\/div>\n<\/form> <\/div>\n <\/div>\n <div class=\"modal-footer\">\n <\/div>\n<\/div>");
That basically means that it is not rendering the HTML like I expect it to, but just spitting out the HTML from the view _tag_users_in_video.html.erb partial.
What I want to happen is for it to pop-up a modal that looks like the modal with id=add-video-step-3, but with the content I specified in _tag_users_in_video.html.erb.
Edit 2
The server log for the above action is:
Started GET "/videos/168/tag_users.js" for 127.0.0.1 at 2015-03-20 10:03:56 -0500
Processing by VideosController#tag_users as JS
Parameters: {"video_id"=>"168"}
User Load (1.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 57 ORDER BY "users"."id" ASC LIMIT 1
FamilyTree Load (0.9ms) SELECT "family_trees".* FROM "family_trees" WHERE "family_trees"."user_id" = $1 LIMIT 1 [["user_id", 57]]
(1.1ms) SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL))) [["user_id", 57]]
Membership Load (1.6ms) SELECT "memberships".* FROM "memberships" WHERE "memberships"."user_id" = 57 AND "memberships"."family_tree_id" = 57
Video Load (1.1ms) SELECT "videos".* FROM "videos" WHERE "videos"."id" = $1 LIMIT 1 [["id", 168]]
Node Load (1.1ms) SELECT "nodes".* FROM "nodes" WHERE "nodes"."media_id" = $1 AND "nodes"."media_type" = $2 LIMIT 1 [["media_id", 168], ["media_type", "Video"]]
ActsAsTaggableOn::Tag Load (1.8ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND "taggings"."context" = 'user_tags' [["taggable_id", 41], ["taggable_type", "Node"]]
Rendered videos/_tag_users_in_video.html.erb (23.6ms)
Rendered videos/tag_users.js.erb (25.5ms)
Completed 200 OK in 196ms (Views: 23.1ms | ActiveRecord: 84.6ms)
Edit 3
So I added the JS render to the format.html inside my save_video action like you suggest. This is the code:
respond_to do |format|
if #node
format.html { render 'tag_users.js' }
format.js
end
end
This is what the result looks like:
Whereas I am trying to get it to look like this:
Edit 4
This is the save_video method in my controller (I left commented out code to see what has been tried with no success):
def save_video
authorize! :read, #family_tree
#video = Video.find(params[:video_id])
if params[:status].to_i == 200
#video.update_attributes(:yt_video_id => params[:id].to_s, :is_complete => true)
#node = current_user.nodes.create!(family_tree: #family_tree, media: #video, name: #video.title, circa: #video.circa)
if #node
render 'tag_users.js'
end
# respond_to do |format|
# if #node
# format.html { }
# format.js
# end
# end
else
Video.delete_video(#video)
end
# respond_to do |format|
# format.html { redirect_to video_tag_users_path(#video, #node) }
# format.js
# end
# redirect_to root_path
# redirect_to video_tag_users_path(#video, #node)
end
Here is the server log for this permutation of the save_video action:
Started GET "/videos/172/save_video?status=200&id=bMaCxSIbJYU" for 127.0.0.1 at 2015-03-20 13:39:19 -0500
Processing by VideosController#save_video as HTML
Parameters: {"status"=>"200", "id"=>"bMaCxSIbJYU", "video_id"=>"172"}
User Load (1.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = 57 ORDER BY "users"."id" ASC LIMIT 1
FamilyTree Load (1.0ms) SELECT "family_trees".* FROM "family_trees" WHERE "family_trees"."user_id" = $1 LIMIT 1 [["user_id", 57]]
(1.2ms) SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL))) [["user_id", 57]]
Membership Load (1.4ms) SELECT "memberships".* FROM "memberships" WHERE "memberships"."user_id" = 57 AND "memberships"."family_tree_id" = 57
Video Load (0.9ms) SELECT "videos".* FROM "videos" WHERE "videos"."id" = $1 LIMIT 1 [["id", 172]]
(0.9ms) BEGIN
SQL (1.3ms) UPDATE "videos" SET "is_complete" = $1, "updated_at" = $2, "yt_video_id" = $3 WHERE "videos"."id" = 172 [["is_complete", "t"], ["updated_at", "2015-03-20 18:39:19.959122"], ["yt_video_id", "bMaCxSIbJYU"]]
(1.5ms) COMMIT
(0.9ms) BEGIN
SQL (5.4ms) INSERT INTO "nodes" ("created_at", "family_tree_id", "media_id", "media_type", "name", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["created_at", "2015-03-20 18:39:19.967237"], ["family_tree_id", 57], ["media_id", 172], ["media_type", "Video"], ["name", "Outro 10PP"], ["updated_at", "2015-03-20 18:39:19.967237"], ["user_id", 57]]
(1.2ms) COMMIT
ActsAsTaggableOn::Tag Load (1.7ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND "taggings"."context" = 'user_tags' [["taggable_id", 45], ["taggable_type", "Node"]]
Rendered videos/_tag_users_in_video.html.erb (10.3ms)
Rendered videos/tag_users.js.erb (12.7ms)
Edit 5
There is no front-end part that sends request to save_video. What happens is, the user fills out the form that appears in this modal:
<div id="overlay"> </div>
<div class="popup" id="add-video-step-4" data-step="4" data-intro="GETS TO UPLOADING">
<div class="titles clearfix">
<h2>Upload a Video</h2>
<p><i>Step 1 of 3</i></p>
</div>
<div class="content">
<% if #family_tree %>
<%= simple_form_for([#family_tree, #video], :remote => true) do |f| %>
<div class="column">
<div class="f-row">
<%= f.input :title, label: "Title:" %>
</div>
<div class="f-row">
<%= f.input :description,label: "Description:" %>
</div>
<div class="f-row">
<%= f.input :circa, as: :datepicker, start_year: Date.today.year - 5, label: "Circa:" %>
</div>
<div class="f-row">
<label for="family">Family in this video:</label>
<%= f.collection_select :user_ids, #family_tree.members.order(:first_name), :id, :first_name, {}, {multiple: true} %>
</div>
</div>
<%= f.button :submit, "Add Video", id: "video-submit" %>
<% end %>
<% end %>
</div> <!-- //content -->
</div> <!-- //popup -->
That modal then sends the request to this Create action in my Video controller:
def create
authorize! :read, #family_tree
#video = Video.new(video_params)
respond_to do |format|
if #video.save
format.html { redirect_to video_upload_path(#video) }
# format.json { render action: 'show', status: :created, location: #video }
else
format.html { render action: 'new' }
format.json { render json: #video.errors, status: :unprocessable_entity }
end
end
end
Which, if successful, then sends the request to this Video#Upload action:
def upload
authorize! :read, #family_tree
#video = Video.find(params[:video_id])
#upload_info = Video.token_form(#video, video_save_video_url(#video))
respond_to do |format|
## Note that I have been tinkering with this, but it doesn't work properly yet
format.html { redirect_to video_tag_users_path(#video, #node) }
format.js
end
end
Which first sends to the video_save in the assignment statement.
Hope that provides clarity.
Edit 6
This is the contents of my application.js
//= require jquery
//= require jquery_ujs
//= require best_in_place
//= require bootstrap-sprockets
//= require jquery-ui/datepicker
//= require best_in_place.jquery-ui
//= require jquery.purr
//= require best_in_place.purr
//= require bootstrap.file-input
//= require chosen.jquery
//= require main.js
//= require spin.min
//= require ladda.min
//= require masonry.js
//= require introjs
//= require pnotify
$(document).ready(function(){
$("input.datepicker").datepicker();
/* Activating Best In Place && Include Success Highlighting & Bounce for comments & videos */
$(".best_in_place").best_in_place().bind("ajax:success", function () {$(this).closest('p, h5').effect('highlight').effect("bounce", { times:3 }, { duration:400}).dequeue(); });
$('.dropdown-toggle').dropdown();
$('#unread-notification').click(function(){
var url = $(this).data('read-url');
$.ajax({
type: "PUT",
url: url
});
});
});
Edit 7
Here is the server log after the first create is called:
Started POST "/family_trees/57/videos" for 127.0.0.1 at 2015-03-23 15:05:46 -0500
Processing by VideosController#create as JS
Parameters: {"utf8"=>"✓", "video"=>{"title"=>"Hello There", "description"=>"This is an interesting video", "circa"=>"", "user_ids"=>[""]}, "commit"=>"Add Video", "family_tree_id"=>"57"}
User Load (15.9ms) SELECT "users".* FROM "users" WHERE "users"."id" = 57 ORDER BY "users"."id" ASC LIMIT 1
FamilyTree Load (5.6ms) SELECT "family_trees".* FROM "family_trees" WHERE "family_trees"."user_id" = $1 LIMIT 1 [["user_id", 57]]
FamilyTree Load (2.2ms) SELECT "family_trees".* FROM "family_trees" WHERE "family_trees"."id" = $1 LIMIT 1 [["id", 57]]
(2.3ms) SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL))) [["user_id", 57]]
Membership Load (1.8ms) SELECT "memberships".* FROM "memberships" WHERE "memberships"."user_id" = 57 AND "memberships"."family_tree_id" = 57
(2.6ms) BEGIN
SQL (6.1ms) INSERT INTO "videos" ("created_at", "description", "title", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", "2015-03-23 20:05:46.637067"], ["description", "This is an interesting video"], ["title", "Hello There"], ["updated_at", "2015-03-23 20:05:46.637067"]]
(2.8ms) COMMIT
Redirected to http://localhost:3000/videos/177/upload
Completed 302 Found in 84ms (ActiveRecord: 39.2ms)
Started GET "/videos/177/upload" for 127.0.0.1 at 2015-03-23 15:05:46 -0500
Processing by VideosController#upload as JS
Parameters: {"video_id"=>"177"}
User Load (2.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = 57 ORDER BY "users"."id" ASC LIMIT 1
FamilyTree Load (1.9ms) SELECT "family_trees".* FROM "family_trees" WHERE "family_trees"."user_id" = $1 LIMIT 1 [["user_id", 57]]
(1.3ms) SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL))) [["user_id", 57]]
Membership Load (1.7ms) SELECT "memberships".* FROM "memberships" WHERE "memberships"."user_id" = 57 AND "memberships"."family_tree_id" = 57
Video Load (2.8ms) SELECT "videos".* FROM "videos" WHERE "videos"."id" = $1 LIMIT 1 [["id", 177]]
Rendered videos/_upload_video.html.erb (4.6ms)
Rendered videos/upload.js.erb (7.6ms)
Completed 200 OK in 344ms (Views: 23.7ms | ActiveRecord: 10.3ms)
Edit 8
_upload_video.html.erb
<div class="bootstrap-styles" id="add-video-step-3">
<div class="modal-header">
<div class="titles clearfix">
<h2>Upload a Video</h2>
<p><i>Step 2 of 3</i></p>
</div>
</div>
<div class="modal-body">
<div class="content">
<%= form_tag #upload_info[:url], :multipart => true do %>
<%= hidden_field_tag :token, #upload_info[:token] %>
<div class="uploader clearfix">
<%= file_field_tag :file, title: 'SELECT FILE TO UPLOAD', class: "upload" %>
</div>
<button class="btn btn-success ladda-button" data-color="green" data-style="expand-left"><span class="ladda-label">Upload Video</span><span class="ladda-spinner"></span></button>
<% end %>
</div>
</div>
<div class="modal-footer">
</div>
</div>
upload.js.erb
$("#add-video-step-4").html("<%= escape_javascript(render 'videos/upload_video') %>");
Assuming this is your code
def tag_users
authorize! :read, #family_tree
#video = Video.find(params[:video_id])
#node = #video.node
respond_to do |format|
render format.html
format.js
end
end
And, by looking at output i can say that server is receiving HTML as format. Since, you want to execute script you must send datatype to script.
Looking at html code, i think you have to pass data: {type: "script"} to simple_form function, so it will be
<div id="overlay"> </div>
<div class="popup" id="add-video-step-4" data-step="4" data-intro="GETS TO UPLOADING">
<div class="titles clearfix">
<h2>Upload a Video</h2>
<p><i>Step 1 of 3</i></p>
</div>
<div class="content">
<% if #family_tree %>
<%= simple_form_for([#family_tree, #video], :remote => true, data: {type: "script"} ) do |f| %>
<div class="column">
<div class="f-row">
<%= f.input :title, label: "Title:" %>
</div>
<div class="f-row">
<%= f.input :description,label: "Description:" %>
</div>
<div class="f-row">
<%= f.input :circa, as: :datepicker, start_year: Date.today.year - 5, label: "Circa:" %>
</div>
<div class="f-row">
<label for="family">Family in this video:</label>
<%= f.collection_select :user_ids, #family_tree.members.order(:first_name), :id, :first_name, {}, {multiple: true} %>
</div>
</div>
<%= f.button :submit, "Add Video", id: "video-submit" %>
<% end %>
<% end %>
</div> <!-- //content -->
</div> <!-- //popup -->
See here Why I need add "data: {type: "script"}" on remote link with rails / ajax
If you want to use the redirect, you might just try adding a format to the redirect path:
format.html { redirect_to video_tag_users_path(#video, format: :js) }
Related
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 %>
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 want to load more comments but it is not working as I wanted, I've checked the console, it is showing no change, here is the code for my _post.html.erb:
<div class="posts-wrapper">
<div class="post">
<div class="post-head">
<div class="thumb-img"></div>
<div class="user-name">
<%= post.user.name %>
<span class="badge"><%= time_ago_in_words(post.created_at) %></span>
</div>
</div>
<div class="image center-block">
<%= link_to (image_tag post.image.url(:medium), class:'img-responsive'), post_path(post) %>
</div>
<div class="post-bottom">
<div class="caption">
<div class="user-name">
<%= post.user.name %>
</div>
<span class="label label-info">caption:</span><span style="color: black"><%= post.caption %></span>
</div>
<div class="comments" id="comments_<%= post.id %>">
<% if post.comments.any? %>
<div class="paginator" id="comments-paginator-<%= post.id %>">
<% unless post.comments.count <= 4 %>
<%= link_to "view all #{post.comments.count} comments", post_comments_path(post), remote: true, class: 'more-comments', data: {post_id: "#{post.id}", type: "html"} %>
<% end %>
</div>
<%= render post.comments.last(4), post: post %>
<% end %>
</div>
</div>
<div class="comment-like-form row">
<div class="like-button col-sm-1">
<span class="glyphicon glyphicon-heart-empty"></span>
</div>
<div class="comment-form col-sm-11">
<%= form_for([post, post.comments.build], remote: true) do |f| %>
<%= f.text_field :content, placeholder: 'Add a comment...',class: "form-control comment_content", id: "comment_content_#{post.id}"%>
<% end %>
</div>
</div>
</div>
</div>
and here is _comment.html.erb
<div class="comment">
<div class="user-name">
<% if comment.user %>
<%= comment.user.name %>
<% end %>
</div>
<div class="comment-content">
<%= comment.content %>
<span class="label label-warning"><%= time_ago_in_words(comment.created_at)%></span>
</div>
<% if comment.user == current_user %>
<%= link_to post_comment_path(post, comment),id:"post#{post.id}comment#{comment.id}", method: :delete, data: { confirm: "Are you sure?" },remote: true do %>
<span class="glyphicon glyphicon-trash"></span>
<% end %>
<% end %>
</div>
and here is comment_controller
class CommentsController < ApplicationController
before_action :set_post
def index
#comments = #post.comments.order("created_at ASC")
respond_to do |format|
format.html { render :layout => !request.xhr? }
end
end
def create
#comment = #post.comments.build(comment_params)
#comment.user_id = current_user.id
if #comment.save
respond_to do |format|
format.html { redirect_to posts_path }
format.js
end
else
flash[:alert] = "Check the comment form, something went wrong."
render posts_path
end
end
def destroy
#comment = #post.comments.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to posts_path }
format.js
end
# flash[:success] = "Comment deleted :("
# redirect_to posts_path
end
private
def comment_params
params.require(:comment).permit(:content)
end
def set_post
#post = Post.find(params[:post_id])
end
end
and here is post controller
class PostsController < ApplicationController
before_action :set_post,only: [:edit,:show,:update,:destroy]
before_action :logged_in_user, only: [:create, :destroy,:new]
before_action :owned_post, only: [:edit, :update, :destroy]
def index
#posts = Post.all.order('created_at DESC').page(params[:page]).per_page(3)
# #posts = Post.all.order('created_at DESC').paginate(page: params[:page])
respond_to do |format|
format.html
format.js
format.json { render json: #projects }
end
end
def new
#post = current_user.posts.build
end
def create
if #post = current_user.posts.create(post_params)
flash[:success] = "Your post has been created!"
redirect_to posts_path
else
flash.now[:alert] = "Your new post couldn't be created! Please check the form."
render :new
end
end
def show
end
def destroy
#post.destroy
redirect_to posts_path
end
def edit
end
def update
if #post.update(post_params)
flash[:success] = "Post updated."
redirect_to posts_path
else
flash.now[:alert] = "Update failed. Please check the form."
render :edit
end
end
private
def owned_post
unless current_user == #post.user
flash[:alert] = "That post doesn't belong to you!"
redirect_to root_path
end
end
def set_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:image, :caption)
end
end
and here is JavaScript in asset to load more comment loadmorecomment.js
$( document ).ready(function() {
$('.more-comments').click( function() {
// alert("ok roi day");
$(this).on('ajax:success', function(event, data, status, xhr) {
event.preventDefault();
var postId = $(this).data("post-id");
$("#comments_" + postId).html(data);
$("#comments-paginator-" + postId).html("<a id='more-comments' data-post-id=" + postId + " data-type='html' data-remote='true' href='/posts/" + postId + "/comments'>show more comments</a>");
console.log("<a id='more-comments' data-post-id=" + postId + " data-type='html' data-remote='true' href='/posts/" + postId + "/comments'>show more comments</a>");
});
});
});
but when I click nothing happens, but in the console it says:
Started GET "/posts/25/comments" for 127.0.0.1 at 2017-08-12 18:39:49 +0700
Processing by CommentsController#index as HTML
Parameters: {"post_id"=>"25"}
Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT ? [["id", 25], ["LIMIT", 1]]
Rendering comments/index.html.erb
Comment Load (0.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ? ORDER BY created_at ASC [["post_id", 25]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 53], ["LIMIT", 1]]
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 53], ["LIMIT", 1]]
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 53], ["LIMIT", 1]]
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 53], ["LIMIT", 1]]
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 53], ["LIMIT", 1]]
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 53], ["LIMIT", 1]]
Rendered collection of comments/_comment.html.erb [5 times] (14.1ms)
Rendered comments/index.html.erb (16.6ms)
Completed 200 OK in 20ms (Views: 17.0ms | ActiveRecord: 0.8ms)
I followed the instructions in this question's answer by emmanuel and the form now finds the Category ID and submits it but does not find the Sub Category ID associated with the Category and does not save it.
The params are taken which can be noted by this,
Parameters: {"utf8"=>"✓", "authenticity_token"=>"PTRTGGblf3HoWNXmanKl8TIP7F4j/QKTLN2Wd6oKSQWSXV27qioztUpXgb6YjHEroaWf8dgTzUIgQiRBK2XxWQ==", "post"=>{"title"=>"200k", "description"=>"FMxd123", "category_id"=>"2", "subcategory_id"=>"9"}, "commit"=>"Create Post"}
It then shows the error message on my screen (with my error partial) that "Sub Category must exist. The SQL output is like so:
(0.2ms) begin transaction
Category Load (0.1ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
(0.0ms) rollback transaction
Rendering posts/new.html.erb within layouts/application
Rendered shared/_errors.html.erb (0.8ms)
Category Load (0.1ms) SELECT "categories".* FROM "categories"
CACHE (0.0ms) SELECT "categories".* FROM "categories"
SubCategory Load (0.1ms) SELECT "sub_categories".* FROM "sub_categories" WHERE "sub_categories"."category_id" = ? [["category_id", 1]]
SubCategory Load (0.1ms) SELECT "sub_categories".* FROM "sub_categories" WHERE "sub_categories"."category_id" = ? [["category_id", 2]]
SubCategory Load (0.1ms) SELECT "sub_categories".* FROM "sub_categories" WHERE "sub_categories"."category_id" = ? [["category_id", 3]]
My Posts.coffee:
jQuery ->
subcat = $('#subcategory-select').html()
$('#category-select').change ->
cat = jQuery('#category-select').children('option').filter(':selected').text()
options = $(subcat).filter("optgroup[label='#{cat}']").html()
if options
$('#subcategory-select').html(options)
else
$('#subcategory-select').empty()
And the part where category_id and sub_category_id are taken in the form with select boxes:
<p>
<%= f.label :category_id%>
<%= f.collection_select(:category_id, Category.all, :id, :name,
{ prompt: 'Select a category' }, { id: 'category-select' }) %>
</p>
<p>
<%= f.label :subcategory_id%>
<%= f.grouped_collection_select :subcategory_id, Category.all, :sub_categories,
:name, :id, :name, { include_blank: 'Select a sub category' },
{ id: 'subcategory-select' } %>
</p>
Confused as to how it isn't working because it made my category_id get saved when it wasn't working. Any ideas?
Gone through your code and I found some errors.
Here are the changes you should make to make your project work.
As you mentioned, it is not any jquery issue.
Error1:-
You have taken the subcategory model name as SubCategory and table is sub_categories, so the foreign key should be sub_category_id, but you have taken subcategory_id.
So either you have to change the column in the database, or tell rails to take the name.
Here are the changes to tell rails about it.
post.rb
class Post < ApplicationRecord
belongs_to :category
# belongs_to :sub_category
belongs_to :sub_category, class_name: 'SubCategory', foreign_key: 'subcategory_id'
end
sub_category.rb
class SubCategory < ApplicationRecord
belongs_to :category
# has_many :posts, :primary_key => "subcategory_id"
has_many :posts, class_name: 'Post', primary_key: 'id', foreign_key: 'subcategory_id'
end
Check the lines commented.
Now the post show view also has some errors which I solved.
Error2:-
posts/show.html.erb:
<% content_for :title, #post.title %>
<% navigation_add #post.title, post_path(#post) %>
<h2 align="center">Title: <%= #post.title %></h2>
<div class="well col-xs-8 col-xs-offset-2">
<h4 class="center description"><strong>Description:</strong></h4>
<hr>
<%= simple_format(#post.description) %>
<hr>
<p>Post ID: <%=#post.id%></p>
<hr>
<div class="post-actions">
<%= link_to "Edit this post", edit_post_path(#post), class: "btn btn-xs btn-primary" %>
<%= link_to "Delete this post", post_path(#post), method: :delete,
data: { confirm: "Are you sure you want to delete the post?"},
class: "btn btn-xs btn-danger" %>
<%= link_to "View all posts", posts_path, class: "btn btn-xs btn-success" %>
</div>
</div>
Last but not the least, your seeds.rb is wrong.
Error3:-
category_1 = Category.where(name:"cat1").first_or_create(name:"cat1")
category_2 = Category.where(name:"cat2").first_or_create(name:"cat2")
#SUB
# 1
SubCategory.where(name: 'g', category_id: category_1.id).first_or_create
SubCategory.where(name: 'er', category_id: category_1.id).first_or_create
#L2
SubCategory.where(name: 'tu', category_id: category_2.id).first_or_create
SubCategory.where(name: 'dual', category_id: category_2.id).first_or_create
Add this script to posts/new.html to get your dropdown work.
<script type="text/javascript">
$(document).ready(function() {
var subcat;
subcat = $('#subcategory-select').html();
return $('#category-select').change(function() {
var cat, options;
cat = jQuery('#category-select').children('option').filter(':selected').text();
options = $(subcat).filter("optgroup[label='" + cat + "']").html();
if (options) {
return $('#subcategory-select').html(options);
} else {
return $('#subcategory-select').empty();
}
});
});
</script>
Here is the working image:
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