In my Rails 4 app, I have a Calendar and a Post models, using shallow routes:
resources :calendars do
resources :posts, shallow: true
end
A calendar has_many post and a post belong_to a calendar.
On Calendars#Index, I display all the posts of a calendar.
I am trying to update the custom approval attribute of a post from this very same view, using an AJAX call, so the page is not reloaded but the new value of the attribute is displayed.
In the calendar index.html.erb file, I have:
<% #posts.each do |post| %>
<tr id="post_row_<%= post.id%>">
... # Truncated for brivety
<td class="cell_content_center post_approval_section">
<% if post.approval == "ok" %>
<span class="ok_green">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "ok"), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-ok" data-toggle="tooltip" data-placement="left" title="Approve Post"></span>
<% end %>
</span><br/>
<% if post.approval == "edit" %>
<span class="edit_yellow">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "edit"), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-repeat" data-toggle="tooltip" data-placement="left" title="Require Edits"></span>
<% end %>
</span><br/>
<% if post.approval == "remove" %>
<span class="remove_red">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "remove"), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-remove" data-toggle="tooltip" data-placement="left" title="To Be Deleted"></span>
<% end %>
</span>
</td>
</tr>
<% end %>
This is my PostsController:
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to post_path(#post) }
format.json { render :show, status: :ok, location: #post }
format.js
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
Then, in the update.js.erb file in the app/views/posts folder, I added:
$('#post_row_<%= j post.id %>').select.('.post_approval_section').html('<%= j render(partial: "calendar_show_approval") %>');
—————
UPDATE: I have also tried with:
$('#post_row_<%= j post.id %> > .post_approval_section').html('<%= j render(partial: "calendar_show_approval") %>');
But I get the same result in the browser and the error in the console.
—————
Finally, I have created a _calendar_show_approval.html.erb partial in the same app/views/posts folder:
<% if post.approval == "ok" %>
<span class="ok_green">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "ok"), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-ok" data-toggle="tooltip" data-placement="left" title="Approve Post"></span>
<% end %>
</span><br/>
<% if post.approval == "edit" %>
<span class="edit_yellow">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "edit"), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-repeat" data-toggle="tooltip" data-placement="left" title="Require Edits"></span>
<% end %>
</span><br/>
<% if post.approval == "remove" %>
<span class="remove_red">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "remove"), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-remove" data-toggle="tooltip" data-placement="left" title="To Be Deleted"></span>
<% end %>
</span>
When I click on one of my three links supposed to update the post approval attribute, nothing happens in the browser and I get the following error message in the console:
PATCH http://localhost:3000/posts/38?post%5Bapproval%5D=remove 500 (Internal Server Error)
send # jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1:9665
jQuery.extend.ajax # jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1:9216
$.rails.rails.ajax # jquery_ujs.self-d456baa54c1fa6be2ec3711f0a72ddf7a5b2f34a6b4f515f33767d6207b7d4b3.js?body=1:94
$.rails.rails.handleRemote # jquery_ujs.self-d456baa54c1fa6be2ec3711f0a72ddf7a5b2f34a6b4f515f33767d6207b7d4b3.js?body=1:177
(anonymous function) # jquery_ujs.self-d456baa54c1fa6be2ec3711f0a72ddf7a5b2f34a6b4f515f33767d6207b7d4b3.js?body=1:406
jQuery.event.dispatch # jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1:4671
elemData.handle # jquery.self-a714331225dda820228db323939889f149aec0127aeb06255646b616ba1ca419.js?body=1:4339
—————
UPDATE 2: here is the content of my log/development.log file:
Started PATCH "/posts/37?post%5Bapproval%5D=ok" for ::1 at 2015-11-19 08:08:12 -0800
Processing by PostsController#update as JS
Parameters: {"post"=>{"approval"=>"ok"}, "id"=>"37"}
[1m[36mUser Load (1.2ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1[0m [["id", 1]]
[1m[35mPost Load (1.5ms)[0m SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT 1 [["id", 37]]
[1m[36m (1.1ms)[0m [1mBEGIN[0m
[1m[35mSQL (3.3ms)[0m UPDATE "posts" SET "approval" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["approval", "ok"], ["updated_at", "2015-11-19 16:08:12.522940"], ["id", 37]]
[1m[36mSQL (7.4ms)[0m [1mINSERT INTO "versions" ("event", "object", "whodunnit", "created_at", "object_changes", "item_id", "item_type") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"[0m [["event", "update"], ["object", "---\nid: 37\ncalendar_id: 6\ndate: 2015-11-18 04:25:00.000000000 Z\nsubject: Subjects\nformat: Link\ncopy: Copy 2\ncreated_at: 2015-11-16 04:25:59.404072000 Z\nupdated_at: 2015-11-19 00:39:30.866318000 Z\nimage_file_name: Capture_d’écran_2015-08-25_à_19.38.59.png\nimage_content_type: image/png\nimage_file_size: 1212743\nimage_updated_at: 2015-11-16 05:35:46.273534000 Z\nshort_copy: Short Copy 2\nscore: \nfacebook: true\ntwitter: true\ninstagram: false\npinterest: false\ngoogle: false\nlinkedin: false\ntumblr: \nsnapchat: \napproval: edit\n"], ["whodunnit", "1"], ["created_at", "2015-11-19 16:08:12.522940"], ["object_changes", "---\napproval:\n- edit\n- ok\nupdated_at:\n- 2015-11-19 00:39:30.866318000 Z\n- 2015-11-19 16:08:12.522940000 Z\n"], ["item_id", 37], ["item_type", "Post"]]
[1m[35m (12.0ms)[0m COMMIT
Rendered posts/_approval.html.erb (0.7ms)
Rendered posts/update.js.erb (2.5ms)
Completed 200 OK in 58ms (Views: 13.2ms | ActiveRecord: 26.5ms)
—————
What am I doing wrong?
Related
I created an AJAX function that allows you to click to refresh posts at the top of the stack. Unfortunately, the ajax function is receiving the wrong parameters and returning server error 500. I am simply trying to load the latest posts available (most recent) I can't catch where the error is coming from. What do I need to do to get the newest posts to load on the stack using AJAX GET in index.html.erb?
posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: %[show edit update destroy share like]
before_action :authenticate_user!
def index
following_ids = current_user.following_users.pluck(:id)
following_ids << current_user.id
#posts = Post.where(user_id: following_ids).order('created_at DESC').page(params[:page])
#post = Post.new
end
def load_more
following_ids = current_user.following_users.pluck(:id)
following_ids << current_user.id
#posts = Post.where(user_id: params[:following_ids]).order('created_at DESC').limit(20)
respond_to do |format|
format.html
format.js
end
end
index.html.erb
<div class="col-md-5">
<div class="post-feed-bg">
<div id="post-index-form" class="post-form-bottom-padding">
<%= render 'posts/form' %>
</div>
<!---LOAD MORE POSTS BUTTON-->
<%= link_to load_more_path(#posts), class: 'bttn-material-circle bttn-danger bttn-md load-more-posts', :remote => true do %>
<i class="fas fa-sync"></i>
<% end %>
<div class="post-textarea-bottom-border"></div>
<div class="text-center">
<%= image_tag 'post/loading.gif', style: 'display: none;', class: 'loading-gif' %>
</div>
<div class="post-feed-container" id="container_posts">
<% if #posts.present? %>
<%= render partial: "posts/posts", locals: {posts: #posts} %>
<% end %>
</div>
</div>
</div>
_posts.html.erb
<% #posts.each do |post| %>
<div class="post-container" data-id="<%= post.id %>">
<div class="media" style="padding-bottom: 2em;">
<%= user_avatar_post(post.user) %>
<div class="media-body post-user-name">
<h5><i class="fas fa-user"></i> <%= link_to post.user.user_full_name, user_path(post.user) %></h5>
<p><%= linkify_hashtags(post.body_text) %> </p>
</div>
</div>
<div class="post-container-charm-bar">
<ul>
<li class="votes" id="#post_<%= post.id %>">
<%= link_to like_post_path(post), style: 'text-decoration: none', class: 'like-btn', method: :put, remote: true do %>
<p id="thumb-id" class="thumbs-up" style="cursor: pointer;">b</p>
<% end %>
</li>
<li><strong class="likes-count"><%= number_with_delimiter(post.get_likes.size) %></strong></li>
<li><%= link_to '#', data: {toggle: "modal", target: "#commentmodal"} do %>
<%= link_to post_path(post, anchor: 'comments') do %>
<i class="far fa-comments post-charm-bar-icon-color fa-2x"></i>
<% end %>
<% end %>
</li>
<li><strong><%= post.comment_threads.size %></strong></li>
<li>
<%= link_to({controller: 'posts', action: 'share', id: post.id}, method: :post, remote: true, style: 'text-decoration: none;') do %>
<i class="far fa-share-square fa-2x "></i>
<% end %>
</li>
<li>
<%= link_to post, style: 'text-decoration: none;' do %>
<i class="fas fa-eye fa-2x"></i>
<% end %>
</li>
<li>
<%= link_to edit_post_path(post), style: 'text-decoration: none;' do %>
<i class="fas fa-pencil-alt fa-2x post-charm-bar-icon-color"></i>
<% end %>
</li>
<li>
<% if current_user == post.user %>
<%= link_to post_path(post), style: 'text-decoration: none;', method: :delete, remote: true do %>
<i class="fas fa-trash-alt fa-2x"></i>
<% end %>
<% end %>
</li>
</ul>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-12 post-image">
<% if post.photo.present? %>
<%= image_tag post.photo.feed_preview, class: 'd-flex align-self-start mr-3 img-fluid rounded', lazy: true %>
<% else %>
<% end %>
</div>
</div>
</div>
</div>
<% end %>
<script type="text/javascript">
$(document).ready(function () {
$("img").lazyload({
effect: "fadeIn",
skip_invisible: true,
threshold: 500
});
});
</script>
index.js.erb
// Load new records
$("#container_posts").prepend("<%= escape_javascript(render(#posts)) %>").hide().fadeIn(1000);
//Append new data
$("<%= j render partial: "posts/#{#post.post_type}", locals: {post: #post } %>").appendTo($("#container_posts"));
//Update pagination link
<% if #posts.last_page? %>
$('.pagination').html("All done");
<% else %>
$('.pagination').html("<%= j link_to_next_page(#posts, 'Next Page', :remote => true) %> ");
routes.rb
resources :posts, on: :collection do
member do
......
end
end
get "/load_more", to: "posts#load_more", as: 'load_more'
load_more_posts.js
$(document).on('turbolinks:load', function () {
$('a.load-more-posts').click(function (e) {
// prevent the default click action
e.preventDefault();
// hide more load more link
$('.load-more-posts').hide();
// show loading gif
$('.loading-gif').show();
// get the last id and save it in a variable 'last-id'
var last_id = $('.post-container').last().attr('data-id');
// make an ajax call passing along our last career insight id
$.ajax({
// make a get request to the server
type: "GET",
// get the url from the href attribute of our link
url: "/posts",
// send the last id to our rails app
data: {
id: last_id,
user_profile: "", // maybe nil in certain cases
_: ""
},
// the response will be a script
dataType: "script",
success: function (data, textStatus, jqXHR) {
if (jqXHR.status == "204") {
$('.loading-gif').hide();
$('.load-more-posts').show();
}
$('.loading-gif').hide();
$('.load-more-posts').show();
},
error: function (jqXHR, exception) {
}
})
});
});
post parameters
=> #<Post id: 59, body_text: "Fix this!", photo: nil, user_id:
2, created_at: "2018-11-02 19:13:09", updated_at: "2018-11-02 19:13:09", post_id: nil, post_id: nil, post_counter: 0, cached_votes_total: 0, cached_votes_score: 0, cached_votes_up: 0, cached_votes_do
wn: 0, cached_weighted_score: 0, cached_weighted_total: 0, cached_weighted_avera
ge: 0.0, hash_id: "DQxad5rRVvfb">
server stacktrace
Started GET "/load_more.%23%3CPost::ActiveRecord_Relation:0x0000000016f89718%3E" for 127.0.0.1 at 2018-11-03 00:32:58 -0400
Started GET "/posts?id=41&user_profile=&_=1541219410513" for 127.0.0.1 at 2018-11-03 00:32:58 -0400
Processing by PostsController#load_more as
Processing by PostsController#index as JS
Parameters: {"id"=>"41", "user_profile"=>"", "_"=>"1541219410513", "on"=>:collection}
User Load (3.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 5], ["LIMIT", 1]]
User Load (2.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 5], ["LIMIT", 1]]
DEPRECATION WARNING: Setting custom parent classes is deprecated and will be removed in future versions. (called from parent_class_name at C:/Ruby24-x64/lib/ruby/gems/2.4.0/bundler/gems/acts_as_follower-c5ac7b9601c4/lib/acts_as_follower/follower_lib.rb:10)
DEPRECATION WARNING: Setting custom parent classes is deprecated and will be removed in future versions. (called from parent_class_name at C:/Ruby24-x64/lib/ruby/gems/2.4.0/bundler/gems/acts_as_follower-c5ac7b9601c4/lib/acts_as_follower/follower_lib.rb:10)
(2.0ms) SELECT "users"."id" FROM "users" INNER JOIN "follows" ON "follows"."followable_id" = "users"."id" AND "follows"."followable_type" = $1 WHERE "follows"."blocked" = $2 AND "follows"."follower_id" = $3 AND "follows"."follower_type" = $4 AND "follows"."followable_type" = $5 [["followable_type", "User"], ["blocked", false], ["follower_id", 5], ["follower_type", "User"], ["followable_type", "User"]]
(58.0ms) SELECT "users"."id" FROM "users" INNER JOIN "follows" ON "follows"."followable_id" = "users"."id" AND "follows"."followable_type" = $1 WHERE "follows"."blocked" = $2 AND "follows"."follower_id" = $3 AND "follows"."follower_type" = $4 AND "follows"."followable_type" = $5 [["followable_type", "User"], ["blocked", false], ["follower_id", 5], ["follower_type", "User"], ["followable_type", "User"]]
Completed 406 Not Acceptable in 127ms (ActiveRecord: 5.0ms)
ActionController::UnknownFormat (ActionController::UnknownFormat):
SERVER Stacktrace Update 2
Rendered collection of posts/_post.html.erb [25 times] (3464.5ms)
Rendered posts/_post.html.erb (2329.4ms)
Rendered posts/index.js.erb (10273.4ms)
Completed 500 Internal Server Error in 109620ms (ActiveRecord: 24197.5ms)
ActionView::Template::Error (undefined method `user_profile' for nil:NilClass):
1: <div class="post-container" id="post_<%= post.id %>" data-id="<%= post.hash_id %>">
2: <div class="media" style="padding-bottom: 2em;">
3: <%= user_avatar_post(post.user) %>
4: <div class="media-body post-user-name">
5: <h5><i class="fas fa-user"></i> <%= link_to full_name(post.user), user_path(post.user) %></h5>
6: <p><%= linkify_hashtags(post.body_text) %> </p>
app/helpers/posts_helper.rb:3:in `user_avatar_post'
app/views/posts/_post.html.erb:3:in `_app_views_posts__post_html_erb__891594994_136890360'
app/views/posts/index.js.erb:6:in `_app_views_posts_index_js_erb__704681650_227473700'
Processing by ExceptionHandler::ExceptionsController#show as JS
Parameters: {"id"=>"41", "_"=>"1541262709872", "on"=>:collection}
Error during failsafe response: Could not render layout: undefined method `[]' for nil:NilClass
C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionview-5.2.0/lib/action_view/layouts.rb:418:in `rescue in _default_layout'
C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionview-5.2.0/lib/action_view/layouts.rb:415:in `_default_layout'
C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionview-5.2.0/lib/action_view/layouts.rb:392:in `block in _layout_for_option'
C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionview-5.2.0/lib/action_view/renderer/template_renderer.rb:96:in `resolve_layout'
_post.html.erb partial is not rendering with user and bypassing helper methods in posts_helper.rb
posts_helper.rb
module PostsHelper
def user_avatar_post(current_user)
if current_user.user_profile.avatar.feed_thumb.url.nil?
inline_svg 'user_dashboard/add-user-avatar.svg', size: '12% * 12%', class: 'd-flex align-self-start mr-3 purple-rounded rounded'
else
image_tag current_user.user_profile.avatar.feed_thumb.url, class: 'd-flex align-self-start mr-3 img-thumbnail rounded'
end
end
def full_name(user)
user.first_name + ' ' + user.last_name
end
end
Updated Post Controller
def load_more
if params[:last_post_id]
following_ids = current_user.following_users.pluck(:id)
following_ids << current_user.id
#posts = Post.where(user_id: params[:following_ids]).where('id < ?', params[:last_post_id]).order('created_at DESC').limit(20)
else
head :no_content
end
respond_to do |format|
format.html
format.js
end
end
rotute.erb
get "/load_more/:last_post_id", to: "posts#load_more", as: 'load_more'
index.html.erb
<!---LOAD MORE POST BUTTON-->
<div class="float-right" style="z-index: 1000;">
<%= link_to load_more_path(#posts.last.id), class: 'bttn-material-circle bttn-danger bttn-md load-more-posts', :remote => true do %>
<i class="fas fa-sync"></i>
<% end %>
</div>
I'm using friendly_id to hash ids for posts.
On your logs, you can see the load_more request has a really weird extension:
Started GET "/load_more.%23%3CPost::ActiveRecord_Relation:0x0000000016f89718%3E"
Rails think's that's the format and does not know how to render that format.
Your route is defined like this:
get "/load_more", to: "posts#load_more", as: 'load_more'
but you are using it like this
load_more_path(#posts)
and the route does not expect a parameter and it ends up using it as a format.
You should add something to the route so you know from what post "load more". I'll do something like:
get "/load_more/:last_post_id", to: "posts#load_more", as: 'load_more'
And use it like
load_more_path(#posts.last.id)
And on the controller you'll have access to params[:last_post_id] so you know you need to load more posts after that post id.
following_ids = current_user.following_users.pluck(:id)
following_ids << current_user.id
#posts = Post.where(user_id: params[:following_ids]).where('id < ?', params[:last_post_id]).order('created_at DESC').limit(20)
I'm using https://gorails.com/forum/switch-state-of-boolean-field as a guide toggle a boolean value. I'm using a partial to display all the objects but only the first object toggles the boolean value. Also, the ajax is not working, I have to refresh the page to show the new boolean value.
Here is posts_controller:
def toggle_confirm
respond_to do |format|
format.html
format.js
end
#post = Post.find_by(params[:id])
#post.toggle!(:confirm)
end
Here is the views/shared/_received_feed partial:
<ol class="posts">
<% #received_feed.each do |feed| %>
<%= render feed %>
<%= link_to "#{ feed.confirm ? 'Confirmed' : 'Disabled' }", toggle_confirm_post_path(feed), method: :patch, remote: :true, class: "btn btn-xs btn-#{ feed.confirm ? 'success' : 'warning' }" %>
<% end %>
</ol>
Here is the views/toggle_confirm.js.erb:
console.log(<%= #post.confirm %>);
<% if #post.confirm == true %>
$(".post-<%= #post.id %> >
a").html('3Confirmed').removeClass('btn-warning').addClass('btn-success')
<% else %>
$(".post-<%= #post.id %> > a").html('Not
Confirmed').removeClass('btn-success').addClass('btn-warning')
<% end %>
$("#post-status-<%= #post.id %>").html("<%=
#post.confirm %>")
Here is the partial for displaying each post views/posts/_posts:
<li id="post-<%= post.id %>">
<span class="user"><%= post.sender.name %></span>
<br>
<span class="image"><%= image_tag post.sender.avatar.url(:thumb) %>
</span>
<br>
<span class="note"><%= post.note %></span>
<br>
</li>
I have followed the answers suggested on other questions on SO (this question and this question ), but for some reason I can't get my like button counter to work properly with ajax. My counter changes only after a refresh, any help is appreciated thanks!
meals_controller.rb
def upvote
#meal.upvote_from current_user
if request.xhr?
render json: { count: #meal.get_upvotes.size, id: params[:id] }
else
redirect_to meals_path
end
end
def unlike
#meal.unliked_by current_user
redirect_to meals_path
end
routes.rb
Rails.application.routes.draw do
devise_for :users
root 'home#index'
resources :meals do
member do
put "like" => "meals#upvote"
put "unlike" => "meals#unlike"
end
end
#upvote.coffee
$(document).on 'ajax:success', 'a.vote', (status,data,xhr)->
$(".votes-count[data-id=#{data.id}]").text data.count
return
#index.html.erb
<p id="notice"><%= notice %></p>
<h1>Listing Meals</h1>
<% #meals.each do |meal| %>
<%= meal.title %>
<br>
<%= meal.descriptionttext %>
<%= link_to like_meal_path(meal), class: "vote", method: :put, remote: true do %>
<button>
<span class="votes-count" data-id="<% meal.id %>"><%= meal.get_likes.size %></span>
</button>
<% end %>
<%= link_to unlike_meal_path(meal), method: :put do %>
<button type="button">
<span><%= meal.get_upvotes.size%></span>
</button>
<% end %>
<br>
<% end %>
<br>
This is a follow-up question on Rails 4: custom action to update only one param with AJAX and Rails 4: select DOM element with dynamically generated id.
I can't figure out how to make things work from the good answers I got, so I would like to start again from a blank slate.
In my Rails 4 app, I have a Calendar and a Post models, set up with shallow routes:
resources :calendars do
resources :posts, shallow: true
end
A calendar has_many post and a post belong_to a calendar.
In the calendar show.html.erb view, I display all the posts that belong to a calendar.
From this calendar show.html.erb view, I need to update the :approval param of a post, with an AJAX call, so that only the DOM element related to the :approval of this particular post is refreshed, not the entire page.
This is the part of the code in calendar show.html.erb that allows me to update the :approval of a post:
<tr id="post_row_<%= post.id%>">
[...] # Truncated for brivety
<td class="cell_content_center post_approval_section">
<% if post.approval == "ok" %>
<span class="ok_green">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "ok", approval_update: true), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-ok" data-toggle="tooltip" data-placement="left" title="Approve Post"></span>
<% end %>
</span><br/>
<% if post.approval == "edit" %>
<span class="edit_yellow">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "edit", approval_update: true), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-repeat" data-toggle="tooltip" data-placement="left" title="Require Edits"></span>
<% end %>
</span><br/>
<% if post.approval == "remove" %>
<span class="remove_red">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "remove", approval_update: true), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-remove" data-toggle="tooltip" data-placement="left" title="To Be Deleted"></span>
<% end %>
</span>
</td>
[...] # Truncated for brivety
</tr>
Then, in posts_controller.rb:
def update
if params["approval_update"]
respond_to do |format|
if #post.update(post_params)
format.js { render :action => "update_post_approval" }
else
format.html { redirect_to :back }
end
end
else
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to post_path(#post) }
format.json { render :show, status: :ok, location: #post }
format.js
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
end
def update_post_approval
respond_to do |format|
format.js
end
end
Note: here, I cannot use the default Posts#Update action, since it is already used by another AJAX call to update the :approval param from the post show.html.erb view, which the reason why we render the update_post_approval custom action.
Then, I have the following app/views/posts/update_post_approval.js.erb file:
$("tr#post_row_#{post.id} > td.post_approval_section").html('<%= j render(partial: "calendars/post_approval") %>');
Finally, I have the following calendars/_post_approval.html.erb partial:
<td class="cell_content_center post_approval_section">
<% if post.approval == "ok" %>
<span class="ok_green">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "ok", approval_update: true), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-ok" data-toggle="tooltip" data-placement="left" title="Approve Post"></span>
<% end %>
</span><br/>
<% if post.approval == "edit" %>
<span class="edit_yellow">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "edit", approval_update: true), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-repeat" data-toggle="tooltip" data-placement="left" title="Require Edits"></span>
<% end %>
</span><br/>
<% if post.approval == "remove" %>
<span class="remove_red">
<% else %>
<span class="approval_blue" %>
<% end %>
<%= link_to post_path(:id => post.id, "post[approval]" => "remove", approval_update: true), remote: true, :method => :patch do %>
<span class="glyphicon glyphicon-remove" data-toggle="tooltip" data-placement="left" title="To Be Deleted"></span>
<% end %>
</span>
</td>
When I click one of the three links in the <td class="cell_content_center post_approval_section"> section to update a post :approval param, the param is actually updated, as we can see in the server logs:
Started PATCH "/posts/38?approval_update=true&post%5Bapproval%5D=ok" for ::1 at 2015-11-20 08:03:50 -0800
Processing by PostsController#update as JS
Parameters: {"approval_update"=>"true", "post"=>{"approval"=>"ok"}, "id"=>"38"}
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Post Load (0.7ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT 1 [["id", 38]]
(0.6ms) BEGIN
SQL (1.1ms) UPDATE "posts" SET "approval" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["approval", "ok"], ["updated_at", "2015-11-20 16:03:50.888587"], ["id", 38]]
SQL (1.3ms) INSERT INTO "versions" ("event", "object", "whodunnit", "created_at", "object_changes", "item_id", "item_type") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["event", "update"], ["object", "---\nid: 38\ncalendar_id: 6\ndate: 2015-11-17 22:09:00.000000000 Z\nsubject: Subject\nformat: Link\ncopy: https://www.wid.la/\ncreated_at: 2015-11-17 22:09:28.713416000 Z\nupdated_at: 2015-11-20 16:03:20.613597000 Z\nimage_file_name: \nimage_content_type: \nimage_file_size: \nimage_updated_at: \nshort_copy: ''\nscore: \nfacebook: true\ntwitter: false\ninstagram: false\npinterest: false\ngoogle: false\nlinkedin: false\ntumblr: \nsnapchat: \napproval: remove\n"], ["whodunnit", "1"], ["created_at", "2015-11-20 16:03:50.888587"], ["object_changes", "---\napproval:\n- remove\n- ok\nupdated_at:\n- 2015-11-20 16:03:20.613597000 Z\n- 2015-11-20 16:03:50.888587000 Z\n"], ["item_id", 38], ["item_type", "Post"]]
(1.6ms) COMMIT
Rendered calendars/_post_approval.html.erb (0.1ms)
Rendered posts/update_post_approval.js.erb (1.5ms)
Completed 200 OK in 27ms (Views: 9.9ms | ActiveRecord: 6.3ms)
However, unless I manually refresh the page, nothing changes on the view.
I have now spent hours on this issue and can't figure out whether the issue is caused by the Ruby or the JS code.
If necessary, I am happy to share more code.
Any idea of what I am doing wrong here?
The mistake is here:
$("tr#post_row_#{post.id} > td.post_approval_section").html('<%= j render(partial: "calendars/post_approval") %>');
Updated
It should be:
$("tr#post_row_<%= #post.id %> > td.post_approval_section").html('<%= j render(partial: "calendars/post_approval", locals: {post: #post}) %>');
I'm trying to add a form to a modal and then submit the form via JS format with remote: true but the form seems to be submitted as HTML instead, causing an unknown format issue. Any help would be appreciated.
Started POST "/create_deliv_extra" for 127.0.0.1 at 2014-06-16 20:38:17 -0400
Processing by DeliveriesController#create_deliv_extra as HTML
Completed 406 Not Acceptable in 21ms
ActionController::UnknownFormat
Form:
</br>
<%= form_tag create_deliv_extra_url, remote: true, class:"form-inline mb10 mt5", id:"extra_f_#{order.id}" do %>
<%= text_field_tag :description, #extra.description, placeholder: "Description", "data-provide"=>"typeahead", autocomplete: :off, "data-source"=>"#{Extra.all.pluck(:description).uniq}", class:"span4" %>
<% if order.cod == true || current_user.role == "Billing" || current_user.role == "admin" || current_user.role == "Exec" %>
<div class="input-prepend">
<span class="add-on">Amount $</span>
<%= text_field_tag :amount, #extra.amount, placeholder: "$000.00", class:"input-xs" %>
</div>
<% end %>
<div class="input-prepend">
<span class="add-on">Quantity</span>
<%= text_field_tag :quantity, #extra.quantity.present? ? "%g" % #extra.quantity : 1, class:"input-xxs" %>
</div>
<% next_d = order.deliveries.present? ? order.deliveries.maximum(:delivery_counter) + 1 : 1 %>
<div class="input-prepend">
<span class="add-on">From</span>
<%= text_field_tag :load_start, next_d, class:"input-xxxs" %>
</div>
<div class="input-prepend">
<span class="add-on">To</span>
<%= text_field_tag :load_end, next_d, class:"input-xxxs" %>
</div>
<%= select_tag :extra_type, options_for_select(["Per Yard","Per Load","Flat Fee"], #extra.extra_type), class:"input-small" %>
<%= hidden_field_tag :order_id, order.id %>
<%= hidden_field_tag :truck_id, #id %>
<%= button_tag "Add", class:"btn btn-danger" %>
<% end %>
Controller:
def create_deliv_extra
#order = Order.find(params[:order_id])
#id = params[:truck_id]
#extra = Extra.create(amount: params[:amount], extra_type: params[:extra_type], order_id: params[:order_id], description: params[:description], quantity: params[:quantity], load_start: params[:load_start], load_end: params[:load_end])
#extras = #order.next_deliv_extras.length > 1 ? "Extras: " + #order.next_deliv_extras : "No Extras"
respond_to do |format|
format.js
end
end
I've also tried adding format: :js in the form_tag but still receive the same error.
I know the question is old, but I got the same problem and found out my application.js was not requiring jquery_ujs. I added it to my application.js file:
//=require jquery
//=require jquery_ujs
Now remote links and forms work as expected :)
I believe your problem may stem from a form_tag being with another form (form_tag, form_for, or html form). If this is the case, just find a way within the html for the first form to begin and end and then start the second form after the first ends.
<%= form_for do %>
...
<%= button_tag "#" %>
<% end %>
<%= form_tag create_deliv_extra_url, remote: true, class:"form-inline mb10 mt5", id:"extra_f_#{order.id}" do %>
...
<%= button_tag "Add", class:"btn btn-danger" %>
<% end %>