I'm trying to auto-refresh a single partial view every 60 seconds on the index page. I tried splitting the actions into two routes, so that the JS would be easier to change and manage. It seems to be a problem with the respond_to block, maybe you can help me with a better approach.
feed_controller.rb
def index
#hashtags = hashtag_refresh
end
def hashtag_refresh
Hashtag.order('created_at DESC').limit(10).uniq
respond_to do |format|
format.js
end
end
feed\hashtag_refresh.js.erb
$('.trends_li_container').html("<%= escape_javascript(render('feed/shared/hashtag_list')).html_safe %>");
routes.rb
get 'feed/hashtag_refresh', to: 'feed#hashtag_refresh'
hashtag_autorefresh.js
//Refresh Hashtags Partial
$(document).ready(function (){
setTimeout(refreshHashtag, 60000)
});
//Calls action refreshing the partial
function refreshHashtag() {
$.ajax({
url: 'feed/hashtag_refresh',
type: 'GET',
dataType: 'script'
})
}
feed/shared/ folder
_hashtag_list.html.erb
feed/ controller folder
hashtag_refresh.js.erb
Server Development Log
Started GET "/feed/hashtag_refresh?_=1462210930323" for 127.0.0.1 at 2016-05-02 13:45:05 -0400
Processing by FeedController#hashtag_refresh as JS
Parameters: {"_"=>"1462210930323"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 5]]
Rendered feed/shared/_hashtag_list.html.erb (0.0ms)
Rendered feed/hashtag_refresh.js.erb (11.5ms)
Completed 200 OK in 50ms (Views: 47.5ms | ActiveRecord: 0.0ms)
try changing your function refreshHashtag() to this
//Calls action refreshing the partial
function refreshHashtag() {
$.ajax({
url: 'feed/hashtag_refresh'
type: 'GET', //POST
dataType: 'script'
})
}
I think the problem is the returning value of hashtag_refresh. You expect it to return a collection of Hashtags, but actually it returns the return value of respond_to, which I don't know what it really is :P
Try modifying your controller like this:
def index
hashtag_refresh do |hashtags|
#hashtags = hashtags
end
end
def hashtag_refresh
yield Hashtag.order('created_at DESC').limit(10).uniq
respond_to do |format|
format.js
end
end
And your javascript
// Refresh Hashtags Partial
$(document).ready(function (){
setInterval(refreshHashtag, 60000)
});
// Calls action refreshing the partial
function refreshHashtag() {
$.ajax({
url: 'feed/hashtag_refresh.js',
dataType: 'javascript'
})
}
By the way, calling setTimeout recursively is preferred over setInterval because setInterval requires manual cancel, and if you forget to cancel, it will run forever. So your javascript can be like this:
//Refresh Hashtags Partial
$(document).ready(function (){
(function refreshHashtag() {
$.ajax({
url: 'feed/hashtag_refresh.js',
dataType: 'javascript'
}).then(function() {
setTimeout(refreshHashtag, 60000);
});
})();
});
Hope it will resolve your problem :)
UPDATE
If you got the error ActionController::UnknownFormat, then it simply means that rails don't recognize the format js or the mime type text/javascript. We can teach rails by adding some config in config/initializers/mime_types.rb
config/initializers/mime_types.rb
# The RFC standard mime type for javascript
Mime::Type.register "application/javascript", :js
# The legacy but widely used mime types for javascript
Mime::Type.register "text/javascript", :js
Mime::Type.register "application/x-javascript", :js
Related
I was hoping someone could help me out on this one, and a possible explanation. I have a rails controller called get_songs that will get a hash of songs from the currently logged in user. That said, whenever a particular button is clicked I want to get the data from the get_songs controller at put it in javascript variable. The following is what I have so far.
playlist.js.erb
function get_songs() {
var mysongs;
$.ajax({
type : 'GET',
url : "getSongs",
dataType : 'json',
success : function(response) {
}
});
}
My controlller
class StaticPagesController < ApplicationController
respond_to :js, :json, :html
def get_songs()
if user_signed_in?
session[:user_id] = current_user.id
present_user = User.find(session[:user_id])
present_user = present_user.playlist.keys
#songs = present_user
respond_to do |format|
format.json { render :json => #songs}
end
end
My routes:
match '/getSongs', to: 'static_pages#get_songs', via: 'get'
If everything was working you would do:
success : function(response) {
mysongs = response;
}
The 'response' parameter on the success function is the result of the ajax call you are sending from your controller; the #songs json.
A simple way to debug your javascript (to check what is the value of your 'response' after the ajax request) is to right-click on your browser and click on 'inspect', then go to the 'Sources' tab, look for your javascript file and click the line where you want to add the debug point (in this case the line with 'mysongs = response', then refresh the page. It should stop running at that point and show the value of 'response'.
I think problem in session. When you send request using ajax, you don't send any cookies and session. So try this
$.ajax({
type:"GET",
beforeSend: function (request){
//your token is here
request.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr("content"));
},
url: "getSongs",
dataType : 'json',
success : function(response) {
console.log(response)
}
});
Also, make sure that you have <%= csrf_meta_tag %> in layouts/application.html.erb
UPD
If you are using gem 'jquery-rails'
and have //= require jquery_ujs in application.js file
Content of csrf_meta_tag automatically will be added to all your ajax requests
I'm new to Rails and I'm trying to submit model data to a controller method, from javascxript, and render the list of results...
function submitResults() {
resultURL = "/result";
resultData = JSON.stringify(results);
$.ajax({
type: "POST",
url: resultURL,
data: { results: resultData},
contentType: "application/html",
dataType: "html"
});
The server shows the controller method is executed and the view is rendered...
Started POST "/result" for 127.0.0.1 at 2014-11-14 17:36:32 -0600
Processing by ResultsController#create as HTML
Result Load (0.7ms) SELECT "results".* FROM "results"
Rendered results/index.html.erb within layouts/application (366.0ms)
Completed 200 OK in 4722ms (Views: 408.3ms | ActiveRecord: 1.3ms)
but the browser doesn't render the view. Here's my create method that's triggered by the $.ajax call...
def create
result = Result.new(result_params)
result.save
#results = Result.all
respond_to do |format|
format.html { render :index }
end
end
Why doesn't the browser load the index view?
You ajax call is not doing anything with the response, define callback functions for it. E.g.:
$.ajax({
type: "POST",
url: resultURL,
data: { results: resultData},
contentType: "application/html",
dataType: "html"
}).done(function(response) {
//attach the response somewhere in the DOM.
});
Check the AJAX doc for all callbacks.
BTW, you usually do not want to load a whole html page through an ajax call. Seems like the page you are rendering includes everything (seems to be using the default layout). In such a case, making AJAX calls can have no benefits (and make things harder) and you might want to do the post through an html form.
I am very close to completing an AJAX delete method but I am confused about an error message that I receive when the AJAX method is completed. Here is the output generated from my terminal when I click on the AJAX method:
started DELETE "/tasks/71" for 127.0.0.1 at 2014-06-02 22:38:03 -0400
Processing by TasksController#destroy as JS
Parameters: {"id"=>"71"}
Task Load (0.5ms) SELECT "tasks".* FROM "tasks" WHERE "tasks"."id" = $1 LIMIT 1
[["id", 71]]
(0.2ms) BEGIN
SQL (0.3ms) DELETE FROM "tasks" WHERE "tasks"."id" = $1 [["id", 71]]
(75.5ms) COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 82ms (ActiveRecord: 76.5ms)
Started DELETE "/" for 127.0.0.1 at 2014-06-02 22:38:03 -0400
ActionController::RoutingError (No route matches [DELETE] "/"):
actionpack (4.1.0) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
Notice the Started DELETE '/' for 127.0 etc. part. What exactly is that telling me? From the output, I see that the AJAX function was completed succesfully. I'm confused as to what the Routing Error is referring to. Can someone explain to me what this is so I may be able to fix it?
Also, this is my controller code for the destroy function.
def destroy
#task = Task.find(params[:id])
#task.destroy
respond_to do |format|
format.html { redirect_to root_path, notice: "Task Successfully Removed, Good job!"}
format.json { render root_path, notice: "Task Successfully Removed, Good job!" }
end
end
As you can see, the code should be correct. I've tried changing render to redirect_to but I still get the same problem. Thse are my routes:
Rails.application.routes.draw do
root 'tasks#index'
resources :tasks, except: [:show]
Finally, this is my ajax.js.erb file:
$(document).ready(function() {
$(this).on('delete', function(event) {
event.preventDefault();
var id = $(this).attr("data-id");
var data_info = $(this);
$.ajax({
type: 'DELETE',
url: Routes.task_path(id),
dataType: 'json',
data: data_info,
success: function(response) {
$(response).remove();
},
});
});
});
Where could the problem be? I don't think its in my ajax.js.erb file because the action completes. If not there then where? Thanks for the help in advance.
-----------EDIT-----------
I just realized that my output used the JS format not JSON to delete an item. Now I have a follow up question as to why that is? I'm even more confused because in the ajax call I specifically specify it as a JSON call not JS. Did I do something wrong?
-----------EDIT-------------
I tried inserting this line of code as recommended by Rick Peck.
format.js { render root_path, notice: "Task Successfully Removed, Good job!", layout: !request.xhr? }
but now I am receiving a 500 internal server error:
started DELETE "/tasks/108" for 127.0.0.1 at 2014-06-03 14:47:36 -0400
Processing by TasksController#destroy as JS
Parameters: {"id"=>"108"}
Task Load (0.2ms) SELECT "tasks".* FROM "tasks" WHERE "tasks"."id" = $1 LIMIT 1 [["id", 108]]
(0.1ms) BEGIN
SQL (0.2ms) DELETE FROM "tasks" WHERE "tasks"."id" = $1 [["id", 108]]
(1.8ms) COMMIT
Completed 500 Internal Server Error in 5ms
NoMethodError - undefined method `empty?' for nil:NilClass:
actionview (4.1.0) lib/action_view/lookup_context.rb:178:in `normalize_name'
actionview (4.1.0) lib/action_view/lookup_context.rb:153:in `args_for_lookup'
What makes this extremely annoying is that I'm unable to use debugger to checkout out what's happening. I've deduced that something is happening in my ajax code. Right here:
$.ajax({
type: 'DELETE',
url: Routes.task_path(id),
dataType: 'json',
data: data_info,
success: function(response) {
$(response).remove();
// Something is wrong here with the remove function undefined method 'empty'.
// Why is the call being sent as JS not JSON
// Where is the 500 error coming from?
},
});
});
I suspect that my response does not contain the information that I want. All I want to do is remove that HTML element that contained my task entry. I can't see what it is though because I can't use debugger. I can't tell if its my ajax logic in the controller or the ajax.js.erb file. Any thoughts?
format.json { render root_path, notice: "Task Successfully Removed, Good job!" }
Why are you rendering the root_path with json? This will be the "root" of your problem - as JSON will just want to return a plain old data object to the browser
JSON
I would highly recommend removing the render part of the json response. You don't need it - if you want to render HTML as a response, you should use the js format:
respond_to do |format|
format.json { render json: "Task Successfully Removed, Good Job!".to_json }
format.js { render root_path, notice: "Task Successfully Removed, Good job!", layout: !request.xhr? }
end
If you look up the Wikipedia definition of JSON, you'll find this:
JavaScript Object Notation, is an open standard format that uses
human-readable text to transmit data objects consisting of
attribute–value pairs. It is used primarily to transmit data between a
server and web application, as an alternative to XML.
This means if you're trying to render HTML with JSON, it goes against convention & will cause problems down the line
--
In terms of why you're sending a JS request, rather than json, I've found Rails to call the JSON mime-type "JS" before today. Although I don't have any references, I think your usage of json should be okay, if you get the render method sorted out (as above)
The problem is the redirect you do in your destroy action. When you use an xhr (ajax) requests other than GET or POST, your browser uses that same request method (i.e. DELETE in your case) for the next request.
You can fix this by passing in a status of 303 like so:
redirect_to root_path, status: 303
This is my ajax handling code:
$.ajax({
url: "shirts/first?page=" + params[:page],
type: "GET"
})
How to tell Ajax to take the results from the next page in the shirts/first file?
I wrote the code as I've shown but it throws a error saying 'syntax error'! How can I solve this?
Also my .js.erb file if its of some help:
$("#container1").append("<%= escape_javascript(render 'shirts/first')%>");
If you're performing ajax pagination, you'll have to ensure you can handle the Ajax request on the controller (using respond_to), and send the correct data:
JS
#app/assets/javascripts/application.js
$("a.pages").on("click", function() {
$.ajax({
url: "shirts/first?page=" + $(this).attr("id"),
type: "GET"
});
});
You'd need to have your pagination buttons with the page's ID for this
Controller
#app/controllers/shirts_controller.rb
def first
#shirts = Shirt.where(your_query)
respond_to do |format|
format.html
format.js
end
end
View
#app/views/shirts/first.js.erb
$("#container1").append("<%= raw(escape_javascript(render 'shirts/first')) %>");
you have mixed the rails params and javascript code, in javascript
url: "shirts/first?page=" + params[:page]
has syntax error because of : charachter, and even if you remove it means you have a javascript object named params and page is a variable which refers to a key in the params object, whereas here params[:page] refers to a querystring which its key is page in the current request from the client.
So change it like:
$.ajax({
url: "shirts/first?page=<%= params[:page] %>",
type: "GET"
});
You have to be careful here, cause the code above means the current page is being loaded with the page in its querystrings like: http://example.com/homepage?page=helloworld and helloworld probably is the other page in your story.
and for your .js.erb file, in rails 3.0.8, you have to wrap every escape_javascript call with raw():
$("#container1").append("<%= raw(escape_javascript(render 'shirts/first')) %>");
I've been googling all day and still couldn't find any answers.So basically in my javascript function, I want to send a GET request to my rails controller and the rails controller will send back a JSON object. Any idea how do I do this? thnx
Using jQuery I would do something like this:
In the selector and event you want, for instance on clicking some element:
$(function() {
$('#foo').click( function(){
var params = '{"field1": "value1", "field2: "value2"}';
$.get('/controller/bar', params, function(data){
alert(data);
});
});
});
Then in your Rails controller:
def bar
/// hack hack hack
render :json => {"response" => "OK"}
end
The in your routes.rb:
match 'controller/bar' => 'controller#bar'
Finally, change "controller" according to your code. Firebug is your friend!
you can use jQuery ajax to make get or post request from javascript.
jQuery.ajax({
url: "url to controller method", // it should be mapped in routes.rb in rails
type: "GET",
data: {field1 :value1, field2:value2}, // if you want to send some data.
dataType: "json"
success: function(data){
// data will be the response object(json)
}
});
response from rails will something similar to the below, you can modify as per your requirement.
respond_to do |format|
format.js { render :json => #json_data }
end