In Rails, I am querying the database to build a data object for highcharts.
Here is my method from my controller:
def build_data_for_chart
data_array = Array.new
#data_array_as_json = ''
#issues.each {
|issue|
# returns an array of KeyIssue objects for a given issue
given_issue_array = KeyIssues.where(issue: issue).all
a = Array.new
#loop through each element extracting the timedate and % and add to new array
given_issue_array.each {
|entry|
a.push([entry.datetime.utc.to_date, entry.percentage])
}
#build the hash for an individual issue
temp_hash = {:name => issue, :data => a, :animation => false}
#add the individual issue and all its data to a final array that contains all the issues.
data_array.push(temp_hash)
}
#data_array_as_json = data_array.to_json.html_safe
end
Now I am trying to pull it out in a script in my view.
--- script ---
var data = $.parseJSON(<%= #data_array_as_json %>);
--- script ---
When I print to console, I can see the objects and all their data. Also when I print to html the output looks correct:
"[{\"name\":\"ABORIGINAL & NATIVE TITLE ISSUES\",\"data\":[[\"1993-11-01\",32],[\"1994-06-01\",27],[\"1994-09-01\",33],[\"1995-06-01\",26],[\"1995-09-01\",24],[\"1996-01-01\",20],[\"1996-09-01\",27],[\"1997-01-01\",33],[\"1997-06-01\",36],[\"1997-09-01\",36],[\"1998-01-01\",37],[\"1998-05-01\",33],[\"1998-09-01\",31],[\"1999-05-01\",30],[\"1999-09-01\",28],[\"2000-01-01\",30],[\"2000-05-01\",31],[\"2000-09-01\",34],[\"2001-01-01\",32],[\"2001-06-01\",29],[\"2001-09-01\",28],[\"2002-02-01\",25],[\"2002-06-01\",27],[\"2002-10-01\",25],[\"2003-02-01\",24],[\"2003-06-01\",26],[\"2003-10-01\",27],[\"2004-02-01\",27],[\"2004-06-01\",26],[\"2005-06-01\",30],[\"2006-06-01\",27],[\"2007-06-01\",31],[\"2008-07-01\",29]],\"animation\":false}]"
But when I go to print the data variable it is null (obviously due to not being valid input). What am I messing up?
FYI..
I needed to wrap it in single quotes.. to make it work..
$.parseJSON(' <%= #data_array_as_json %> ');
You can try this:
<script type="text/javascript">
var data = <%== data_array.to_json %>
</script>
Related
I have a set of templates that contain key phrases denoted by %%key%% (could use different delimiters if these are a problem). In the code presented, the names of the templates are shown in a selector, and when selected, their values are presently being moved into a textarea for display. Before they are displayed, I wish to go through the template and replace each key with the value associated with that key.
I have tried using template.gsub 'key' 'value', template.gsub! 'key' 'value', and even template['key'] = 'value', to no avail. To eliminate other problems, I have tried using simple values for the 'value' and then displaying the result in an alert. If I don't try the replacement, the alert shows the template. If I try any of these attempts, I don't get the alert to show, indicating some kind of javascript error, I suppose. I can't figure out what the error is.
Here is a part of the application_helper.rb:
#----------------------------------------------------------------------------
def render_haml(haml, locals = {})
Haml::Engine.new(haml.strip_heredoc, format: :html5).render(self, locals)
end
#----------------------------------------------------------------------------
def create_template_selector
get_templates()
render_haml <<-HAML
%select{{name: "msg", id: "template_selector"}}
- #t_hash.each do |name,message|
%option{ :value => message }= name
HAML
end
#----------------------------------------------------------------------------
def get_templates()
templates = Template.all
#t_hash = Hash.new
templates.each do |t|
#t_hash[t.name] = t.message
end
end
and this is the view partial _text.html.haml, where the selector is embedded and its selection is presented when changed:
= form_for(#comment, remote: true, html: {id: "#{id_prefix}_new_comment"}) do |f|
= hidden_field_tag "comment[commentable_id]", commentable.id, id: "#{id_prefix}_comment_commentable_id"
= hidden_field_tag "comment[commentable_type]", class_name.classify, id: "#{id_prefix}_comment_commentable_type"
%div
%h3 Select a Template
= create_template_selector
%div
= f.text_area :comment, id: "#{id_prefix}_comment_comment", name:"text_msg"
.buttons
= image_tag("loading.gif", size: :thumb, class: "spinner", style: "display: none;")
= f.submit t(:add_note), id: "#{id_prefix}_comment_submit"
#{t :or}
= link_to(t(:cancel), '#', class: 'cancel')
:javascript
$(document).ready( function() {
$('#template_selector').change(function() {
var data= $('select').find('option:selected').val();
//
// Here is where I put alert(data) and it works
// but,
// var filled = data.gsub '%%first_name%%' 'Ralph'
// followed by alert(filled), shows no alert panel and no error
//
$("##{id_prefix}_comment_comment").val(data);
});
} );
How can I create a set of fill_ins like:
def fill_ins()
#fillins = Hash.new
#fillins['%%first_name%%'] = 'Ralph'
#fillins['%%last_name%%'] = 'Jones'
...
end
and create a function like:
def fill_in(template)
#fi = fill_ins()
#fi.each do 'fkey, fval'
template.gsub! fkey fval
end
end
and have it work?
In :javascript block, you should be writing JavaScript, not Ruby.
String#gsub is a Ruby method.
String.prototype.replace is a JavaScript method.
var filled = data.replace(/%%first_name%%/g, 'Ralph');
EDIT: Forgot that replace with a string only replaces once. Use regular expression with global flag instead.
Also: to pass the data from Ruby to JavaScript, use this pattern in your template:
<script>
const fillIns = <%= fill_ins.to_json %>;
</script>
Then you can either loop that array and run the replace method with each pair (not optimal) — or you can use a regular expression that picks up on the general pattern of the variable:
var filled = data.replace(/%%([^%]+)%%/g, (_, name) => fillIns[name]);
I have a Rails backend that would serve JSONs like this: (This e.g. is 2.json)
{"id":2,"name":"Magic","location":"Cyberjaya","surprise_type":"Great","instructions":"test","status":"awesome","pricing_level":3,"longitude":"2.90873","latitude":"101.655027","created_at":"2016-02-02T07:19:18.247Z","updated_at":"2016-02-02T12:59:14.403Z"}
and an AngularJS app.js code that goes like this (the relevant parts only):
.factory('MarkersLoc', function($resource) {
debugger;
return $resource("http://localhost:3000/surprises/:id.json");
})
.factory('Markers', function(MarkersLoc) {
var markers = [];
return {
getMarkers: function(){
return MarkersLoc.query().$promise.then(function(response){
debugger;
markers = response;
console.log("Markers: ", markers);
return markers;
});
}
}
})
The problem that I'm having is that, even at the point of the debugger, response is an array of objects that have all the attributes from the JSON except longitude, latitude, created_at and updated_at.
Unfortunately I am unable to determine the reason why these four key-value pairs are omitted when it's being read and returned. Is there something that should be controlling which key-value pair is being processed that I have left out on? Wouldn't the entire JSON be parsed and converted into the object?
The missing values are the result of the data being serialized by the controller on the backend. To view all the keys, ensure all the attributes are defined in the serializer:
class SurpriseSerializer < ActiveModel::Serializer
attributes :id,
:name,
:location,
:surprise_type,
:instructions,
:status,
:pricing_level,
# Add the missing attributes to the serializer
:longitude,
:latitude,
:created_at,
:updated_at
end
I have tried a variety of escaping and unescaping options, but don't understand why my erb is not rendering properly.
I have standard picture url in the format:
https://i.ytimg.com/vi/pB-5XG-DbAA/hqdefault.jpg;
entered into my controller as the following:
#whats_hot_last_vid = #whats_hot_last.video.picture
When I try to render it in my js.erb file:
var lastsongImg = <%= #whats_hot_last_vid %>;
Here's how it renders:
var lastsongImg = https://i.ytimg.com/vi/pB-5XG-DbAA/hqdefault.jpg;
From what I can see, it renders '//' in the http address as the beginning of a JS comment, leading to raising various errors like
Uncaught SyntaxError: Unexpected token :
Any ideas?
The best way to deal with variables like this in js blocks in erb is to use .to_json. This works with strings, arrays, and hashes (which it will convert to json objects). Basically it does the "right thing", and you don't need to worry about wrapping extra formatting around it depending on what type of object it is.
//string
var lastsongImg = <%= #whats_hot_last_vid.to_json %>;
// => var lastsongImg = "https://i.ytimg.com/vi/pB-5XG-DbAA/hqdefault.jpg";
//arrays
<% myArray = [1, "abc", 1.6] %>;
var myArrayJs = <%= myArray.to_json %>;
// => var myArrayJs = [1, "abc", 1.6];
//hashes
<% myHash = {:foo => "bar", :chunky => "bacon"} %>;
var myObject = <%= myHash.to_json %>;
// => var myObject = {"chunky":"bacon","foo":"bar"};
EDIT: as a side note, ActiveRecord objects have the to_js method as well, and produce an object like this:
{"car":{"id":123 "color":"red", "make":"Ford", "model": "Mondeo"}}
You can of course overwrite this for particular models if you want.
You have to put qoutes around the string, like this
var lastsongImg = "<%= #whats_hot_last_vid %>";
Hope it helps =)
I've got a function that queries my database and gets a list of usernames-- I've pasted it below:
*dbQuery.jsp*
<%!
org.json.JSONArray dbQuery(String SQL_STRING)
{
// This step will read hibernate.cfg.xml and prepare hibernate for use
org.hibernate.SessionFactory sessionFactory = new org.hibernate.cfg.Configuration().configure().buildSessionFactory();
org.hibernate.Session session1 = sessionFactory.openSession();
org.hibernate.Query query = session1.createQuery(SQL_STRING);
java.util.List list = query.list();
org.json.JSONArray jsonArray = new org.json.JSONArray(list);
// Actual contact insertion will happen at this step
session1.flush();
session1.close();
return jsonArray;
}
%>
I then try to parse through the list of users, but can't get it to work right. Here's what I'm doing:
var users = <%=dbQuery("FROM Users")%>;
alert("User= " + users[0].getAttribute('username'));
Why doesn't this work? What is the right syntax to parse through the objects/attributes in this JSON Array?
users[0].getAttribute('username')
will not work
try
users[0].username
I need to visualize data for my trac Plugin. Therefore I want to use Open Flash Charts 2.
Trying to follow this didn't quite work out as expected.
Question
The Chartdata won't show, the only output is the loading-animation by OFC.
Everything looks similar too the html-source in the tutorial.
How can I load the JSON- Data into my chart?
Additional Information
I wrote a template where the processed data should be entered.
CHART_TEMPLATE = Template(
'''
<script type=\"text/javascript\" src=\"$json_path/json2.js\">
</script>
<script type=\"text/javascript\" src=\"$js_path/swfobject.js\">
</script>
<script type=\"text/javascript\">
swfobject.embedSWF(\"$ofc_path/open-flash-chart.swf\",
\"$chartname\", \"$width\", \"$height\", \"9.0.0\");
function open_flash_chart_data()
{
alert('reading data');
return JSON.stringify($json_chart_data);
}
function ofc_ready()
{
alert('ofc_ready');
}
</script>
<div id=\"$chartname\"></div>
'''
)
The data is transformed to JSON with Open Flash Charts python, which seems to work well.
def chartdata_from_timetable(self, dict, title):
'''
creates chartdata in JSON-format from 2 dim dictionary
'''
elements = []
x_labels = []
dc = DateConversion.DateConversion()
# if startdate on a weekend, startdate might
not be inluced in the dict->
choose next monday
for key in timetable[startdate]:
element = Chart()
element.type = "line"
element.text = key
values = []
for date in dict:
values.append(dict[date][key])
x_labels.append(string_from_date(date))
element.values = values
elements.append(element)
chart = Chart()
chart.x_axis.labels = x_labels
chart.title.text = title
chart.elements = elements
return chart.create().encode()
Afterwards the following data is returned, none seems to be missing:
CHART_TEMPLATE.safe_substitute(js_path = config['js_dir'],...,
json_chart_data = chart_data)
You have to check if the path of the ofc folder in trac.ini is right.
The function chartdata_from_timetable is also not right. You only see the values of the last entry because of overwriting.