Using JSON with jRails - javascript

I am currently trying to use AJAX in my application via jRails. I am trying to return a JSON object from my controller, and then parse it in my Javascript. I am using json2.js to do the parsing.
Here is the code I currently have:
function getSomething()
{
$.ajax({
type: "GET",
url: "map/testjson",
success: function(data) {
var myData = JSON.parse(data[0]);
window.alert(myData.login);
}
});
}
and in the controller:
class Map::MapController < ApplicationController
def index
end
def testjson
#message = User.find(:all)
ActiveRecord::Base.include_root_in_json = false
respond_to do |w|
w.json { render :json => #message.to_json }
end
end
end
The window.alert simply says 'undefined' (without tics).
However, if I change the javascript to window.alert(data) (the raw object returned by the controller) I get:
[{"salt":"aSalt","name":"",
"created_at":"2010-03-15T02:34:25Z","remember_token_expires_at":
null,"crypted_password":"aPassword",
"updated_at":"2010-03-15T02:34:25Z","id":1,"remember_token":null,
"login":"zgwrig2","email":"zach#zach.com"}]
This looks like an array of size 1, if I'm looking at it correctly, but I have tried just about every combination of JSON.parse on the data object that I can think of, and nothing seems to work.
Any ideas on what I'm doing wrong here?
EDIT
This seems to work fine if there is more than one row in the Users table.

When there are more than one row, what you are deal is a String of your object in json format, not your json object representation.
Really sorry for me english, i want explaind better ...
And if #message is a null object, because there isnt any messange, the render to json dont make anything, and when you are in your JS, you will have a problem because you dont have any response which worker. You must check your #message object. Maybe you can do that:
w.json {render :json => (#message.nil?) ? 0 : #checkpoint }
then, in your callback function you must check if your data response is "0" (like string) or one object.

I can see what you have 2 problems in your code.
It is better if you use $.getJSON to do a JSON request.
jQuery is yet a parser of JSON... then in your callback function you only must do:
$(data).each(function(i, user){
// what you like do with a user
});
In your rails response there a error, is not a w.json { render :json => #message.to_json }, is only w.json { render :json => #message }. Whiout ".to_json".
Hope that helps.

Related

How to pass JavaScript GetElementById string value to Rails?

I have a method to translate different strings in Product class from English language to another. It has two variables: string and language. And for the first one I expect to get current value of the text area. Here how it looks like in JS:
var primary_value = document.getElementById('primary_body_html_value').getElementsByClassName('note-editable')[0].innerText;
And then I want to use this method inside JS function:
var translated_string = "<%= GoogleTranslator.translate(primary_value, 'de') %>"
The main question is how can use this 'primary_value' inside 'translated_string'? As I know - I can use Ajax but I am a bit new to this and I don't understand how to write correctly a method for Ajax and for Product controller. In case if you need a controller code:
class ProductsController < AuthenticatedController
before_action :set_product, only: %i[show edit update]
def index
if params.include?('id')
redirect_to edit_product_path(params[:id]) and return
end
end
def edit
redirect_to products_path, error: 'product not found' unless #product
render :edit_polaris
end
def update
if #product.update(product_params)
render json: {
status: :ok,
notice: 'Saved successfully!'
}, status: 200
else
render json: {
status: :error,
error: 'Something Went Wrong'
}, status: 400
end
end
private
def product_params
params.permit(
:id,
primary_locale: {},
locales: {}
)
end
def set_product
#product = Product.find(product_params[:id])
end
end
This is just a sketch but hopefully can help you out.
It can be inside one of your existing controller methods, for the sake of the example lets say you added a route (and controller method) called translated_string to ProductsController.
#ProductsController
def translated_string
primary_value = params[:primary_value]
#translated_string = GoogleTranslator.translate(primary_value, 'de')
render json: {translated_string: #translated_string}
end
Now when something happens on your DOM page where primary_value is set, you send primary_value via ajax to translated_string and you get the json response with the translated string back - u can do whatever you want with it. This is just an example, there are a million ways to go about it, hope this gives you a direction.

Rails 4/AJAX GET data from controller

I posted a very poor question about this earlier, so I am reposting and making it MVCE.
I'm building a messaging service with Rails and AJAX. So far I can submit a message through a form, it will update in the HTML DOM, an AJAX POST method will send it to the controller, and the controller will save it in the database.
Now I need to add an AJAX method that will GET the message that was just submitted -- so that other users (in other browsers) will be able to view it.
Currently, and this is a hack job way of doing it, in my JS code I set a timeout that calls an AJAX GET function every half second. Is there a better way to do this -- as in, once the controller saves the message can it call the AJAX function? The AJAX code looks like this:
function retrieveMessages(){
var message;
<%debugger%>
$.ajax({
type:"GET",
url:"<%= messages_get_path %>",
dataType:"json",
data: { what_goes_here: "blah" }, //this is the part I do not understand -- see below
success:function(data){
message = data;
console.log(data)
}
});
setTimeout(retrieveMessages, 500);
}
$(document).ready(function(){
//get messages
setTimeout(retrieveMessages, 500);
... more irrelevant
The line data: { what_goes_here: "blah" } doesn't make sense to me. What is the syntax for the controller to send data back to be stored into data:? Furthermore, from the console I can see that what_goes_here is being passed as a parameter to the controller -- again this doesn't make sense to me.
My route looks like this get 'messages/get', :to => 'messages#get' (this might be incorrect?)
rake routes shows
messages_get GET /messages/get(.:format) messages#get
And as of now, I don't have anything in my controller other than a respond_to because at this point I'm just trying to call the controller. What is the syntax to send data back to the AJAX method?
def get
debugger
respond_to do |format|
format.html
format.json {render json: #variable} //is this #variable being passed to the AJAX call?
end
end
UPDATE
This makes more sense to me... the AJAX method simply calls the def get function. The def get function then finds the message in the database, and stores it in an instance variable. Subsequently, I can add some Javascript code that will insert it into the DOM. However I must have something wrong in my routing because I'm getting (in the console) http://localhost:3000/messages/get 404 (Not Found)
What you are doing, as you suspect, is not effective. The more users are online the more will be load from these refreshing requests, most of them probably returning no new data.
You should consider more active way of notifying your browsers about changes on the server. One option is to use ActionCable.

Use a controller variable in javascript (Ruby on Rails)

I want to use my controller variable in my javascript.
Since this cannot be done straightforward. I use gon gem. https://github.com/gazay/gon
With this what I do is in a before filter of my base controller (Which acts as a before filter for all the controllers) I do gon.variable_name = value And in my js file I use gon.variable_name. This works fine for full page reloads.
But the variable is not getting updated for ajax request.
Say for example:
On page reload, in my controller I do
gon.variable_name = value1
and in my js, gon.variable_name gives me value1.
After a ajax request in my controller I do
gon.variable_name = value2
and in my js, I still see gon.variable_name as value1 only.
Is there any way I could update gon.variable_name in a ajax request?
Thanks
You can use the watch: true switch for gon:
#app/views/layouts/application.html.erb
<head>
<%= include_gon(watch: true) %>
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def update_vars
#value1 = User.count
gon.watch.value1 = #users_count
end
end
This is what the documentation says. I don't agree with it, but should work.
It looks like ajax polling which is notoriously inefficient.
--
To give you some context, you have to remember that gon basically creates a small hash of javascript in your layout, populating it with the gon variables you've assigned in your controller:
<script>
gon = {
value1: "test",
value2: "test"
}
</script>
We've used it before here:
The reason this is important is because this gon JS variable is invoked at runtime -- meaning that it remains static until you reload the page.
The way around this is to either dynamically reload the gon variable values (using watch above) or pass the new value through your ajax request (like Sergio recommended in the comments):
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def update
respond_to do |format|
format.json { render json: {value_2: "test"}.to_json %>
end
end
end
You'd then be able to use it as follows:
$.ajax({
url: "/update",
success: function(data) {
var value2 = data.value2;
}
});
I have to initialize gon for every request inorder to update the variables.
include_gon(:init => true)
in the response of every request solved the problem.
Extra tip:
For those who use ajaxify rails gem you can call this helper method in the ajaxify_extra_content method and in the content_inserted callback you can append this to the head tag to get it work in a generic way.
Thanks all for your suggestions and help.

How to properly pass a JSON in rails

I am new to web development and rails as well. I created a web app for internal use in php and now am converting it to rails. Trying to find out what render does is difficult. For example I find definitions like this:
render(options = nil, extra_options = {}, &block) protected
Renders the content that will be returned to the browser as the response body.
It seems nobody told the author that you do not use a word in its definition.
I was trying to understand render because according to How to pass json response back to client that is a better way of doing the task than the approach I have tried. But without the other peices I do not know how to implement it.
Could be due to my lack of web experience so if anyone has any links to definitions thats may help please post them.
I get this error:
Error in GetData: JSON.parse: expected property name or '}' at line 2 column 3 of the JSON data
When I print the string in an alert box it appears as one long string so I do not know where "line 2" is. If I set the limit to 1 I get the same error which really makes "line 2" difficult to find.
Here is an example of the data I get back:
[{"DocumentNbr":"SS9230","DocumentRevision":""},{"DocumentNbr":"SS8640","DocumentRevision":"17"},{"DocumentNbr":"SS8618","DocumentRevision":"4"},{"DocumentNbr":"SS8630","DocumentRevision":"20"},
I don't know if the " is supposed to be spelled out as &quot or at least thats how it is displayed in the alert box. I do not know if thats normal or an error that is causing the JSON.parse to fail. Any other ways to check data besides the alert?
I have a javascript function to call 'GetData' in the view:
var wholeNumberData;
wholeNumberData = GetData('wholeNumber', wholeNumber);
Which looks like this (stripped down version):
function GetData(getType, param) {
var data;
var params;
params = 'wholeNumber=' + param;
data = SendRequest('wholenumber/index', params);
return data;
}
function SendRequest(source, params) {
var http = new XMLHttpRequest();
http.open("GET", source + '?' + params, false);
http.setRequestHeader("Content-type","application/json");
http.onload = function() {
//alert('in function');
}
http.send(params);
alert(http.responseText);//Works
return JSON.parse(http.responseText);//FAILS
}
The route wholenumber/index points to an index.html.erb cionatining this:
<% #list = Wholenumber.where("DocumentNbr LIKE ?", params[:wholeNumber] + "%").limit(10) %>
<%= #list.to_json(:only => [:DocumentNbr, :DocumentRevision]) %>
This is kind of an unusual way to do it, but you could just add html_safe to your to_json method and it should work how you have it.
<%= #list.to_json(:only => [:DocumentNbr, :DocumentRevision]).html_safe %>
If you want the control to render JSON, rather than trying to parse JSON from html, you can have the controller action do something like this:
def action
#list = Wholenumber.where("DocumentNbr LIKE ?", params[:wholeNumber] + "%").limit(10)
render json: #list.to_json(:only => [:DocumentNbr, :DocumentRevision])
end
The Rails Guides have a more thorough walkthrough of Rails rendering

How to retrieve a value from an AJAX call with Rails?

I have this scheme:
JS:
jQuery.validator.addMethod(
"check_membership",
function() {
console.log('A');
$.ajax({
type: "POST",
url: "/subscriptions/check_validity",
dataType:"JSON",
data: {coupon: "12345"},
});
console.log('<%= #aaa %>');
},
"mmmmm"
);
and Rails action:
def check_validity
#aaa = 'xxx'
respond_to do |format|
format.js { render :text => #aaa }
end
end
My goal is to display in Javascript the value from Rails - #aaa, but the output of
console.log('<%= #aaa %>');
is just an empty space...
But I am not sure what the proper workflow should be here (I need to pass just a kind of information like "yes"/"no").
Thanks guys!
Ajax sends a params variable of your data to the controller, just like a form for a new record. In your example, to retrieve the coupon value, you pass params the key you established in your ajax call:
def check_validity
value = params[:coupon] # returns "12345"
...
end
As noted in another answer, this will not yield the #aaa value in your console.log, or anywhere in your javascript. These variables are interpreted on the server side, but javascript only works on the client side (unless you're using server side javascript, but that's a horse of a different color). This can be confusing because we use Ruby variables in Views, but Views are interpreted on the server, before they are sent to the client. Javascript is not.
Once you pass a variable to Rails, through the params value, you'll need to send any new information back to the client, which is looks like you're trying to do with :text => #aaa. Many ways to tackle this issue, but you could start with the Railscast:
http://railscasts.com/episodes/324-passing-data-to-javascript
and also
http://railscasts.com/episodes/136-jquery-ajax-revised
Hm, a lot of confusion going on here:
console.log('<%= #aaa %>');
Is mixing server side and client side stuff. If you
render :text => #aaa
in rails, you don't get a variable named #aaa in your browser.
I'd recommend rendering json to the browser anyway...

Categories

Resources