Accessing Rails child objects within Javascript - javascript

I'm very new to rails, so please bear with me. I haven't quite grasped all the "magic" just yet.
Basically I need to access Location objects in Javascript, which all contain 0-N Coordinates. I'm pretty sure the model is set up right, with each Coordinate having a location_id.
I managed to get a parsed JSON of Location objects using the following method: I put
def index
#locations = Location.all.to_json
end
in the controller, and accessed this in the view with
var theLocations = <%= #locations.html_safe %>;
when I show this variable in the log, however, it doesn't show the Coordinates, which kind of makes sense. Thing is, I was planning to iterate over all the Locations and for each one create a javascript var with the relevant coordinates. These vars would then be passed to Google maps as objects.
Basically I was planning on doing something like (pseudocode):
for(Location l in Locations){
get all Coordinate objects within Location
for(Coordinate c: Coordinates);
var myObject = new google.maps.LatLng(c.X, c.Y),
add myObject to list for this location.
}
}
I'm just not sure how to approach this. How can I get a reference to the Coordinates within the Locations?

The quick and dirty answer is to pass a parameter in your to_json call:
#locations = Location.all.to_json(:include => :coordinate)
You may also want to consider creating a custom JSON structure by overriding as_json and rendering the objects as JSON after that.

Related

How to access object in parsed nested JSON in Google Apps Script

Broad spectrum apology, to start off with, for any mistakes relating to being a n00b when it comes to code, js, Google Apps Script and indeed stackoverflow.com.
I am trying to extract the polyline from an API call to Google Maps' Directions API. Parsed from the API results, I get:
{routes=[{summary=A215, copyrights=Map data ©2017 Google, legs=[{duration={text=18 mins, value=1108}, start_location={lng=-0.1295712, lat=51.4227696}, distance={text=7.2 km, value=7187}, start_address=London SW16 6ET, UK, end_location={lng=-0.0706306, lat=51.3869032}, duration_in_traffic={text=15 mins, value=882}, end_address=Woodside Green, London SE25 5EU, UK, via_waypoint=[], steps=[{duration={text=1 min, value=6}, start_location={lng=-0.1295712, lat=51.4227696}, distance={text=29 m, value=29}, travel_mode=DRIVING, html_instructions=Head <b>north</b> on <b>Streatham High Rd</b>/<b>A23</b> toward <b>Streatham Common N</b>/<b>A214</b>, end_location={lng=-0.1297011, lat=51.42301399999999}, polyline={points=iozxHxhXo#X}},....
My script is as follows:
function listJourneyPoints(value) {
//Temporary url for var value
var value = "https://maps.googleapis.com/maps/api/directions/json?origin=SW16%206ET&destination=SE25%205EU&mode=driving&region=UK&departure_time=1507676400&key=AIzaSyDbswrt7RFy3s13ulO9BUY9jQUNchUfi4o";
//Call the google route planner api
var routeResponse = UrlFetchApp.fetch(value);
//Parse JSON from routeResponse
var json = routeResponse.getContentText();
var data = JSON.parse(json);
//Get the polyline
var polyl = data["routes"]["legs"]["steps"]["polyline"];
Logger.log (polyl);
}
I can't work out how to navigate through the arrays and objects to the polyline. I know that dot notation doesn't work with arrays so have used square brackets, but whatever I try I cannot progress past data["routes"]["legs"] without getting 'TypeError: cannot read property "steps" from undefined'. I'm aware the problem probably lies with my not understanding the data structure, but after hours of searching, including using an online Json Parser to elucidate the structure, I'm still stuck, so would be grateful for any help. Thanks!
When working with complicated nested JSON, I like to Logger.log() multiple times as I navigate through it to get a better look at what's going on. Even without that though, adding some formatting to the JSON to see the structure of it and removing unneeded entries can both be helpful in seeing how to access specific elements:
{
routes: [{
legs: [{
steps: [{
polyline: {
points: iozxHxhXo#X
}
}]
}]
}]
}
So the first thing to notice is that routes holds an array, which means we need to access its indices to access the nested objects. Luckily, all of the nested elements are wrapped in an object so we can just access the first element of the array: data["routes"][0]. If I continue to have trouble as I work my way down into the nested objects, I'll keep using Logger.log(data["routes"][0]...) to see what the next key/index should be.
It looks like you had a pretty good idea of the hierarchy and you were just missing the array portion of the objects, which is why you were getting the errors. So adding in [0]'s after each key call should fix your problem.
Also, just as a sidenote, you can use dot notation when accessing keys in an object in Google Scripts, i.e. data.routes[0].legs[0].steps[0].polyline (which returns the polyline object).

Convert string to name of object (casting)

I want to cast a string to an existing object.
Background: I am using only JS, no libraries and no server side code. I have existing objects with elements I wish to display. I pass the name of the object using a query string so it arrives as a string. Example ?Room=Cube and what I wind up with is
nextRoom = getQueryString(); // which returns a string
and I want to display the Cube object. However nextRoom contains "Cube" and JS is not helpful, if I call a display function:
display(nextRoom)
Javascript treats it as a string and fails. Currently I fake it out with the object:
castToObj{"Cube":Cube, "Other":Other, "Etc":Etc, ........}
.....
room = castToObj[nextRoom]; // accessing the object returns the room Object
then I can display the room by calling:
display(room); // now JS treats the parameter as an object
But this requires me to rewrite code to modify the castToObj{} contents every time I add a room. I would like a way to turn "Cube" into Cube, in other words turn a string into an object. I have tried many variations but have been unsuccessful. I could list ways I have tried but that seems senseless because they were all failures.
HELP! PLEASE!
P.S I retired about twenty years ago before learning C++, OOP, etcetera so my javascript skills are just my "C" programming experience expanded.
First create an empty container object:
myElements = {};
Then change your code wherever you define an element, from
Cube = ... whatever ...
to
myElements.Cube = ... whatever ....
for all of your elements (Other, Etc ...).
After this, you simply use
nextRoom = getQueryString();
display(myElements[nextRoom]);
You can use java script eval function but depending on the situation it might open your program to XSS attack. You should use it carefully.

Ruby and Javascript: passing a Ruby array as a Javascript variable

I'm trying to dynamically draw a Google Map and place a marker on it. In my controller, I assemble an array containing the name of the businesss, latitude, longitude and a z-index.
I have an array in Ruby that is available to my Rails view:
#locations = [["Location One",36.0552,-114.928,1]]
When I try to use that array in some Javascript:
var loc = <%= #locations %>
I see this in view source:
var loc = [["Location One",36.0552,-114.928,1]]
In order for the map to display the variable needs to read like:
var loc = [['Location One',36.0552,-114.928,1]]
With the quotes intact around the first element of the array. If I hard code that last line into the Javascript the map renders correctly. It really seems to be the quot; tags that are messing things up.
There will be more than one location on the map so I thought an array of arrays would be the best way to get the needed data into my view.
How can I accomplish this? Thanks.
Edit Corrected following DNNX's comment.
I think you need to convert it to json (a subset of JavaScript) before rendering:
require "json"
...
var loc = <%= #locations.to_json.html_safe %>
you need to use html_safe to prevent the escape the quote

Update subsection of mapped knockout object

I know this question sounds familiar, but I have read so many of the similar questions and have not been able to find my specific situation.
I have a javascript object called gds (GlobalDataStructure). As its name suggests, this object contains all the information I need for all the web pages of my project and is stored in localStorage (hence why I am not just updating view model and need to map in the first place). It contains all sorts of feeds that are read via AJAX.
I use a constructor function to create gds. To massively simplify this structure and hopefully make this question simple, let's say gds was
function gdStructure(){
this.lastUpdate = new Date(2010,1,1);
this.family = new Object();
this.series = new Object();
this.product = new Object();
}
so I have
gds= new gdStructure();
then once i have populated the js array with data from initial feeds, I do the following.
viewmodel = ko.mapping.fromJS(gds);
ko.mapping.fromJS(gds,viewmodel);
The view model is then bound to each page with
ko.applyBindings(viewmodel);
So this all works no problem. This issue arises when I, for example, get a new family feed and I want to update that object. I can do the following
gds.family=feed;
ko.mapping.fromJS(gds,viewmodel);
And all would work fine, but that is mapping a MASSIVE JS object every time. This is extremely slow so I need to find a way where I can update just the feed that has changed. ideally something like..
ko.mapping.fromJS(gds.family, viewmodel.family);
But this appears not to work. Also because it is an OBJECT I can't just do.
viewmodel.family(gds.family)
Can anybody help me? I am sure this must be so simple.
Thanks in anticipation.
I think you have missunderstood how the lib works, this part looks very strange
viewmodel = ko.mapping.fromJS(gds);
ko.mapping.fromJS(gds,viewmodel);
Your using the definition as data?
Anyway, I use ko.mapping like this (A bit simplified but i think you get the point)
http://jsfiddle.net/QtyGd/1/

Storing JS arrays and objects in a database

I have an application that lets users build things in JS. I want the user to be able to save the current state of his work to reuse it or share it, but what he has is a collection of JS objects stored in a JS array, with very different properties (color, label, x/y position, size, etc.).
SQL seems terrible for that particular task, forcing me to maintain tables for every different object, and alas I know very little about NoSQL database. What tools would you use to perform this ? MongoDB sounds promising but before I learn a whole new DB paradigm I want to be sure that I am heading in the right direction.
Object to string:
You can store your objects in the DB as a JSON string. Here's a simple example:
var foo = new Object();
foo.Name = "James";
foo.Gender = "Male";
//Result: {"Name":"James","Gender":"Male"}
var stringRepresentation = window.JSON.stringify(foo);
Here's a working fiddle.
String to object:
To convert your string back to an object, simply call window.JSON.parse():
var myObject = window.JSON.parse(stringRepresentation);
Here's a working fiddle.
If you have no interest in quering the objects for their various properties but only persist them to save state, you can serialize the entire array to JSON and store it in any db you like as one string.
What's on the server?
Most languages have mature JSON implementations that convert JavaScript objects to native types, which you can then easily store in a SQL database.

Categories