In my scenario in rails application after sharing content to facebook i will get a response object with post id
post_id: "mypostidhere"
If its not successful i will get response object with an error message.
So according to the response i want to change a boolean column of last row for the current user in my database table. And for this in my .js.erb file i tried to access current_user.model.last but it throws the following error.
undefined local variable or method `current_user' for
So how can i change the boolean column in database according to the response?
UPDATED
Ajax code
$.ajax({
type: "POST",
url: "/action"
});
Controller code
def action
current_user.modal.last.toggle!(:boolean-column-name)
end
It changes the table column successfully. But after that i am receiving an error in browser CONSOLE as below
POST http://URL/action
500 (Internal Server Error)
I am new to AJAX. What i am doing wrong in ajax request? Thanks in advance.
current_user is not a local variable to your JS function/file, it is a helper provided and available in your rails application.
So, what I will like to ask is:
How are you using current_user in the JS file?
What you can do is to make an ajax call to a controller method, and then access current_user directly from the controller.
If you want to change the db, you're going to have to communicate with your Rails app, which is done with ajax:
#app/assets/javascripts/application.js
... // your events will fire
$.ajax({
url: "/users/update",
method: "PUT",
data: { param: "value" }
success: function(data) {
// do something here
};
});
This will allow you to do the following:
#config/routes.rb
resources :users do
put :update, on: :collection
end
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def update
current_user.update(update_params)
end
private
def update_params
params.permit(:param)
end
end
Related
I want to update elements in the page to tell a user in real-time how many objects will be affected by their choice of criteria in a form.
For an example to work with, the form asks for a number and the django logic will delete any model instance with a pk less than that value once the submit button is clicked - but before clicking the user wants to know how many they will be deleting:
<span id="number-changed">NULL</span> objects will be deleted
so the end result I want is that #number-changed will be populated by a value like MyModel.objects.filter(pk__lt=input_number).count().
I have set up an AJAX call on changes to the input via:
$("input").change( function() {
$.ajax({
type: "GET",
url: "{% url 'myapp:bulkdelete' %}",
data: {
csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
},
success: function (data) {
// code to update #number-changed
}
I am wondering how I implement in the view so that on successful GET the success function can use the value I retrieve. Some pseudo-code:
# views.py
class MyView(FormView):
# ...
def get(self, request, *args, **kwargs):
input_number = ???
number_changed = MyModel.objects.filter(pk__lt=input_number).count()
# presumably some super().get() call here
return ???
Questions:
Can I retrieve the current input_number via request or does it need to be passed as a url parameter when making the AJAX request?
How can I add my required information, number_changed in this case, to the return of the get() method, and how to access this inside success?
The way I have implemented AJAX with django before has being using POST requests and I simply return a JsonResponse with my required data. However, an initial get() is called when loading the page and needs to return a full HttpResponse - so ultimately is there a way to add my additional information into this, or am I going about it completely wrong.
An Ajax request is exactly the same as any other request from the point of view of the server. You can just include the data in the querystring, which you then access in the view via the request.GET dict.
jQuery will generate that querystring for you from the data parameter; note, you don't need a csrf token for a GET request. So:
type: "GET",
url: "{% url 'myapp:bulkdelete' %}",
data: {
input_number: $(this).val(),
},
...
And in the view:
def get(self, request, *args, **kwargs):
input_number = request.GET["input_number"]
I have a problem with Ajax and how can I update info on my HTML page without reloading it.
So, I have a function in my views.py file:
def index(request):
some stuff
context = {
some stuff
}
return render(request, "header.html", context)
And I just use variables from {context} in my header.html file. And the question is - how can I perform index function and send new variables to my header.html file without reloading it?
First, create a new endpoint to get the desired data in whichever format. I prefer JSON.
New endpoint:
# views.py
from django.http import JsonResponse
def new_endpoint(request):
"""Returns `JsonResponse` object"""
# you can change the request method in the following condition.
# I dont know what you're dealing with.
if request.is_ajax() and request.method == 'GET':
# main logic here setting the value of resp_data
resp_data = {
'html': 'stuff',
# more data
}
return JsonResponse(resp_data, status=200)
Then, you need to code the AJAX part calling this endpoint with the method, data, headers, etc. and finally, define the success callback method to get the desired data.
AJAX:
var data = {};
$.ajax({
url: '/your-new-endpoint-url',
type: 'GET',
data: data,
dataType: 'json',
success: function(resp) {
$('#changingElement').html(resp.html);
}
});
You can send any type of data from this new endpoint to change whatever element's html text or class name or styles, etc.
I'm trying to retrieve some information calling a method through ajax. It seems I'm missing something on my code, because when troubleshooting from chrome inspect I get an "url not found" error. My Models are Warehouse & Product. What i would like to accomplish is when a product is selected from the select_tag field, populate a text_field with a default price for that product. This is what I have so far:
1. select_tag view:
<%= select_tag "product_selection", options_from_collection_for_select(Product.all, "id", "name") %>
2. warehouses.js
$(document).on("change", '#product_selection', function() {
$.ajax({
url: "/warehouses/get_price",
type: "GET",
dataType: "json",
data: { product_id: $('#product_selection option:selected').value() }, // This goes to Controller in params hash, i.e. params[:file_name]
complete: function() {},
success: function(data, textStatus, xhr) {
// Do something with the response here
document.getElementById("default_price").value = data.default_price;
},
error: function() {
alert("Ajax error!")
}
});
});
3. warehouses_controller.rb
def get_price
#price = Product.find(params[:product_id]).price
if request.xhr?
render :json => { :default_price => #price }
end
end
4. routes.rb
resources :products
resources :warehouses
resources :warehouses do
member do
get 'get_price'
end
The message I get from Chrome Inspect:
jquery.self-c64a743….js?body=1:10244 GET http://localhost:3000/warehouses/get_price?product_id=2 404 (Not Found)
Check out Rails routing here: Rails Routes
Routes are read from the top down, and so it looks for :get_price in the first reference to warehouses. One choice is Combine the routes:
resources :products
resources :warehouses do
member do
get 'get price'
end
end
That will actually point to
/warehouses/{:id}/get_price
To lose the restful id, you could try
resources :products
resources :warehouses do
collection do
get 'get price'
end
end
That should respond to
/warehouses/get_price
and then pass the appropriate parameter.
Alternatively, To get the route that you are looking for, you could
get 'warehouses/get_price', to: 'warehouses#get_price'
resources :products
resources :warehouses
Notice the custom route is above the resources.
The Ajax call to the method (url: "warehoueses/get_price") was failing because I generated the get_price method inside the private methods section on warehouses_controller.rb so that was basically my mistake. Thanks anyway for the help!
I wrote a search action in Ember.js for search results from Tornado server. Now the problem is when search not found any results I raise an error using tornado.web.HTTPError(statuscode):
Server.py:
=========
if not rows:
raise tornado.web.HTTPError(400)
I'm trying to handle the error in my App.js file like this:
App.js:
========
search: function() {
// the current value of the text field
var query = this.get('query');
data = $.ajax({
dataType: "json",
url: "/search?query=" + query,
async: false}).error(function(response) {
alert(response.responseText);
}).responseJSON;
In above code when Tornado raises an error, .error(response) is executed, but responseText is empty.
How can I catch that error and redirect to an error page?
Issue is not from EmberJS. Its in Ajax Request. You are requesting for data-type of JSON but for 404 you are sending HTML content(probably like this <html><title>400: Bad Request</title><body>400: Bad Request</body></html>) which after parsed returns empty. Either remove data-type as JSON from AJAX Request or write your own custom handler like this in server to return 404 error in JSON mode.
class MyHandler(tornado.web.RequestHandler):
def get(self):
self.clear()
self.set_status(400)
self.finish("[]") //some JSON
I'm trying to send an AJAX request to my rails controller (the make_suggestion method in the items controller).
I have the following javascript:
$.ajax({
url: "/items/make_suggestion", // pass to make_suggestions in recipes controller
type: "POST",
dataType: 'json',
data: parsed_data // a Javascript object/data hash
});
With debug(params) on, I'm not seeing any of the parsed_data in the params.
Can anyone please point out what is wrong? And how do I create symbols in the params in Rails through firing AJAX?
UPDATES
In my controller, I have
def make_suggestion
respond_to do |format|
format.html
format.json { render :json => params }
end
end
My ajax code:
$.ajax({
url: "http://localhost:3000/items/make_suggestion", // I'm doing the proper routing later, since '/make_suggestion' routes to 'items/1/make_suggestion'
type: "POST",
dataType: 'json',
data: parsed_data,
success: function(returned_value){
if(returned_value)
alert('true');
$('.test').append(returned_value);
},
error: function(returned_value){
$('.test').html('<p>Error in AJAX request</p>');
alert('Not working');
}
});
And my parsed_data looks like this:
Parameters: {"data1"=>{"position"=>"1", "item_id"=>"item_1",
"to_do"=>"unknown ", "selected"=>"false"}, "data2"=>{"position"=>"2",
"item_id"=>"item_2", "to_do"
=>"unknown", "selected"=>"false"}, "data3"=>{"position"=>"3", "item_id"=>"item_3 ", "to_do"=>"unknown", "selected"=>"false"},
"data4"=>{"position"=>"4", "item_id "=>"item_4", "to_do"=>"unknown",
"selected"=>"false"}, "data5"=>{"position"=>"5" , "item_id"=>"item_5",
"to_do"=>"unknown", "selected"=>"false"}}
But when I went to /items/make_suggestion.json, it's only showing the following:
{"action":"make_suggestion","controller":"recipes","format":"json"}
You can view / trace parameters in multiple ways
1) tail your rails log file tail -f log/development.log, note that the rails web server usually starts tailing to the console once started
2) raise exceptions and view debug output in the browser
3) use the javascript console in your browser (some are built-in), also consider Firefox with Firebug plug (use the 'console') tab
Tailing the rails log
every single request made to your rails server will show all of the parameters passed, as well as the controller and action which received the request and all sql statements generated
consider adding the 'awesome_print' gem to your application for better logging output, once installed logger.ap params will give you a nice readable output
Raise exceptions
not needed very often but if you add raise "ZOMG" as the first line of your controller action, it will render html output and show all the parameters passed. This is almost useless for ajax calls
Javascript Console
This will show all ajax requests and all parameters that javascript is sending to the rails server and all data being returned as well, very useful
Rails will map the javascript ajax parameters to a ruby hash, this is very nice as these data structures are almost exactly the same in the browser as they are in rails, i.e.
// javascript data structure
var parsed_data = {
foo: "FOO",
bar: "BAR",
person: {
first_name: "Joe",
last_name: "Smith"
}
}
output to the log using awesome_print would result in a ruby hash something along the lines of
logger.ap params
{
:foo => "FOO",
:bar => "BAR",
:person => {
:first_name => "Joe",
:last_name => "Smith"
}
}
# access the data
params[:foo]
# => "FOO"
params[:person][:first_name]
# => "Joe"
Your data post to controller not detail.
look my example :
$.ajax({
url:'/contact/new',
type:'get',
data:{object_param:{
first_name:'zainulmasadi',
last_name:'masadi ganteng',
phone_number:'089745674119541'}},
dataType:'json',
success:function(returned_value){
if(returned_value)
alert('true');
}
})
and my controller
def new
#contact = ContactPhone.create(params[:object_param])
if #contact.save
respond_to do |format|
format.html
format.json {render :json => #contact}
end
end
end