Backbone toJson doesn't return attributes when id is a string - ruby-on-rails

I am running some rails code to generate json to be consumed by backbone. When I treat the id like a string, and consume it in backbone, the toJSON() function doesn't return the attributes. When I call a to_i on the id, toJSON() works properly. (But this breaks my app because "012345" is different from 12345.
My backbone view:
serialize: ->
console.log #model.toJSON()
info: #model.toJSON().info
non-working json response:
{"id":"123456","info":[{"label":"Hire Date","text":"06-NOV-00"},{"label":"User ID","text":"YADDA"},{"label":"Employee Number","text":"123456"}] }
non-working toJSON result:
data_partition: DataPartition
id: "123456"
__proto__: Object
working json:
{"id":123456,"info":[{"label":"Hire Date","text":"06-NOV-00"},{"label":"User ID","text":"YADDA"},{"label":"Employee Number","text":123456}] }
working toJSON():
data_partition: DataPartition
id: 123456
info: Array[3]
__proto__: Object
But this breaks my rails app when I chop off leading 0's.

Running this code I don't find any issue:
var responseJSON_1 = {"id":"123456","info":[{"label":"Hire Date","text":"06-NOV-00"},{"label":"User ID","text":"YADDA"},{"label":"Employee Number","text":"123456"}] };
var responseJSON_2 = {"id":123456,"info":[{"label":"Hire Date","text":"06-NOV-00"},{"label":"User ID","text":"YADDA"},{"label":"Employee Number","text":"123456"}] };
var MyModel = Backbone.Model.extend({});
var myModel_1 = new MyModel( responseJSON_1 );
var myModel_2 = new MyModel( responseJSON_2 );
console.log( myModel_1.toJSON() );
console.log( myModel_2.toJSON() );​
Check the working jsFiddle
Are you sure you are not changing more things in your response than the id format?

Related

How to get a value from SecretString returned from AwsCustomResource (service: 'SecretsManager', action: 'getSecretValue') as plain text?

I'm modifying the code from this workshop to do cross-account rather than cross-region.
https://cdk-advanced.workshop.aws/start.html
The first thing I did was install and configure cdk-assume-role-credential-plugin and bootstrapped.
In the workshop they use a AwsCustomResource to get around the cross-region limitation of StringParameter.valueFromLookup.
static valueFromLookup(scope, parameterName) Requires that the stack this scope is defined in will have explicit account/region information. Otherwise, it will fail during synthesis.Using an AwsCustomResource allows them to override the region from stack.
const targetKeyLookupCR = new cr.AwsCustomResource(this, 'TargetKeyLookup', {
onUpdate: { // will also be called for a CREATE event
service: 'SSM',
action: 'getParameter',
parameters: {
Name: props.targetKeyIdSsmParameterName
},
region: props.targetRegion,
physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString())
},
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({resources: [parameterArn]})
});
Unfortunately you cannot override account of stack in a similar fashion. Adding an assumedRole does not help either. It always looks for parameter in stack's account.
I tried to use SecretsManager & AwsCustomResource to get around that cross-account limitation:
const targetKeyLookupCR = new cr.AwsCustomResource(this, 'TargetKeyLookup', {
onUpdate: {
service: 'SecretsManager',
action: 'getSecretValue',
parameters: {
SecretId: props.targetKeyIdSsmParameterName
},
assumedRoleArn: 'arn:aws:iam::111111111111:role/MultiRegionS3CrrKmsCmkXacct',
region: props.targetRegion,
physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString())
},
policy: cr.AwsCustomResourcePolicy.fromSdkCalls({resources: [parameterArn]})
});
const secretString = targetKeyLookupCR.getResponseField(dataPath);
The code above returns a string that looks like this.
"{"password":"/];asdf(5;{ASDF=L%UuVxasDFHg`(:l","MyKeyID":"arn:aws:kms:us-west-1: 111111111111:key/1111a22b-3c44-5ddd-66e7-f8f9999a1111"}"
I can see it in CloudWatch:
2021-08-14T04:34:15.641Z c5ae47f7-1e4a-43a3-a475-d0d16ea7e1be INFO Responding {"Status":"SUCCESS","Reason":"OK",...
"SecretString":"{"password":"/];asdf(5;{ASDF=L%UuVxasDFHg`(:l","MyKeyID":"arn:aws:kms:us-west-1: 111111111111:key/1111a22b-3c44-5ddd-66e7-f8f9999a1111}"...}
In the workshop they use the response directly:
role.addToPolicy(new iam.PolicyStatement({
resources: [targetKeyLookupCR.getResponseField('Parameter.Value')],
actions: ['kms:Encrypt'] }));
To get the Value of MyKeyID, I've tried...
JSON.parse and splitting the string. No matter what I try ends up with an error like 'Unexpected token $ in JSON at position 0' or 'TypeError: Cannot read property 'split' of undefined'
This led me to https://docs.aws.amazon.com/cdk/latest/guide/tokens.html#tokens_json, which I definitely thought was going to be the answer! It was not. More 'Unexpected token $ in JSON at position 0' errors.
const stack = cdk.Stack.of(this);
const secretString = targetKeyLookupCR.getResponseField('SecretString');
const jsonString = stack.toJsonString(secretString);
const jsonObj = JSON.parse(jsonString);
Update:
From this https://docs.aws.amazon.com/cdk/api/latest/docs/core-readme.html#cfnjson I got a different error that indicates it has the right string, but just can't parse it properly. Unexpected token p in JSON at position 3 at JSON.parse ().
const secretString = targetKeyLookupCR.getResponseField('SecretString');
const cfnJson = new CfnJson(this, 'cfn-json', {
value: secretString,
});
// #ts-ignore
const myKeyId = cfnJson.MyKeyID || '*';
This is because CfnJson adds quotes around string:
"Value": {
"Fn::Join": [
"",
[
"\"",
{
"Fn::GetAtt": [
"MySourceTargetKeyLookupACF65EAE",
"SecretString"
]
},
"\""
]
]
}
I'm not sure how to proceed. How would I get the ARN from secretString as plain text?
I guess I was looking for a more elegant solution, but this works...
const secretString = targetKeyLookupCR.getResponseField('SecretString');
const myKeyId = cdk.Fn.select(7,cdk.Fn.split('"', secretString));
It splits the secretString into an array using double quote as delimiter
cdk.Fn.split('"', secretString)
and selects the 7th item from array produced by split
cdk.Fn.select(7, <array>)

cannot get extjs grid to populate with proxy data call

I have gone from incorporating extjs in my original asp.net application which worked when hardcoding any data stores and binding them to the charts/grids. When I tried proxy url calls or even fetching the data from code behind and wrapping in json I still do not get the data into the grid. So I gave up and went with extjs and nodejs and still using mongodb; this worked perfectly but I still have to learn to create a better UI using express/jade etc which is a different project now. But then I came across using MVC with extjs and with a sample project tried the same thing (the sample had hardcoded data) and I cannot for the life of me get it to display the data.
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.state.*'
]);
Ext.onReady(function () {
Ext.QuickTips.init();
// setup the state provider, all state information will be saved to a cookie
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{ name: 'username', type: 'string' }
]
});
Ext.define('UserStore', {
extend: 'Ext.data.Store',
model: 'User',
autoload: true,
proxy: {
type: 'ajax',
url: '/dashboard.aspx/getDBData',
reader: {
type: 'json',
root: 'users'
},
listeners:
{
exception: function (proxy, response, operation) {
Ext.MessageBox.show(
{
title: 'REMOTE EXCEPTION',
msg: operation.getError(), icon: Ext.MessageBox.ERROR, buttons: Ext.Msg.OK
});
}
}
}
});
var myStore = Ext.getStore('UserStore');
the url I am including here is the codebehind function that I initially tried which accesses the mongodb and returns json result. Not working.
Now from the extjs node.js application I have results coming into localhost:3000/userlist which returns a list from mongodb and displays it as follows:
extends layout
block content
h1.
User List
u1
each user, i in userlist
li
a(href="mailto:#{user.email}")= user.username
Now would it be possible to use the same server and call the base url and then change the route.js file to return the mongodb json result or call the mongodb localhost:27017 and get a result. Really confused here
exports.index = function(db) {
return function(req, res) {
var collection = db.get('usercollection');
collection.find({},{}, function(e,docs){
res.render('userlist', {
"userlist" : docs
});
});
};
};
EDIT:
First thing I realized from asp.net perspective was that I was not calling a webservice just a codebehind method. Any comments will still be appreciated.
EDIT 2:
{"connTime":null,"userName":"101591196589145","clientName":null,
"feedUrl":null,"dconnTime":null,"errMessage":null,"ip":null}
You have identified a root in your store as 'users'
reader: {
type: 'json',
root: 'users'
},
But there is no root in your returned json such as:
{"users":[{"connTime":null,"userName":"101591196589145","clientName":null,
"feedUrl":null,"dconnTime":null,"errMessage":null,"ip":null}]}

backbone.js load text file into a collection

This is first time I am using a framework for development and stuck with the very first step.
I am converting a Flex application to Javascript application and using backbone as framework.
I have to load a text file which is in name value format.
<!doctype html>
<html>
<head>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js'></script>
<script>
var ResourceBundleCollection = Backbone.Collection.extend({
url:'ResourceBundle.txt',
});
var resourceBundleCollection = new ResourceBundleCollection();
resourceBundleCollection.fetch();
</script>
</head>
<body>
</body>
</html>
The ResourceBundle.txt includes the content in following format
location_icon=../../abc/test.png
right_nav_arrow_image=assets/images/arrow.png
right_nav_arrow_image_visible=true
It is throwing following error
not well-formed
I could load the text file easily using JQuery and parse it
$.ajax({
type : "GET",
url : "ResourceBundle.txt",
datatype : "script",
success : resourceXMLLoaded
});
and parse it using the following code
var lines = txt.split("\n");
for(var i=0;i<lines.length;i++) {
if(lines[i].length > 5) {
var _arr = lines[i].split("=");
resourceBundleObj[$.trim(_arr[0])] = $.trim(_arr[1]);
}
}
Please advice how to achieve the same results in backbone.js
If you MUST use plain text to support this, you can override Backbone.Collection.parse to achieve what you need.
In addition to that, you may also want to create a ResourceBundleModel to host each item in the ResourceBundleCollection.
You can see a demo here: http://jsfiddle.net/dashk/66nkF/
Code for Model & Collection is here:
// Define a Backbone.Model that host each ResourceBundle
var ResourceBundleModel = Backbone.Model.extend({
defaults: function() {
return {
name: null,
value: null
};
}
});
// Define a collection of ResourceBundleModels.
var ResourceBundleCollection = Backbone.Collection.extend({
// Each collection should know what Model it works with, though
// not mandated, I guess this is best practice.
model: ResourceBundleModel,
// Replace this with your URL - This is just so we can demo
// this in JSFiddle.
url: '/echo/html/',
parse: function(resp) {
// Once AJAX is completed, Backbone will call this function
// as a part of 'reset' to get a list of models based on
// XHR response.
var data = [];
var lines = resp.split("\n");
// I am just reusing your parsing logic here. :)
for (var i=0; i<lines.length; i++) {
if (lines[i].length > 5) {
var _arr = lines[i].split("=");
// Instead of putting this into collection directly,
// we will create new ResourceBundleModel to contain
// the data.
data.push(new ResourceBundleModel({
name: $.trim(_arr[0]),
value: $.trim(_arr[1])
}));
}
}
// Now, you've an array of ResourceBundleModel. This set of
// data will be used to construct ResourceBundleCollection.
return data;
},
// Override .sync so we can demo the feature on JSFiddle
sync: function(method, model, options) {
// When you do a .fetch, method is 'read'
if (method === 'read') {
var me = this;
// Make an XHR request to get data
// Replace this code with your own code
Backbone.ajax({
url: this.url,
method: 'POST',
data: {
// Feed mock data into JSFiddle's mock XHR response
html: $('#mockData').text()
},
success: function(resp) {
options.success(me, resp, options);
},
error: function() {
if (options.error) {
options.error();
}
}
});
}
else {
// Call the default sync method for other sync method
Backbone.Collection.prototype.sync.apply(this, arguments);
}
}
});
Backbone is designed to work with a RESTful API through JSON natively. It however is a library that is flexible enough to fit your need, given enough customization.
By default a collection in Backbone will only accept a JSON formatted collection.
So you need to convert your input to JSON format:
[{"name": "name", "value": "value},
{"name": "name", "value": "value}, ...
]
Of course you can override the default behaviour:
Overriding backbone's parse function

Loop through html tables data and submit back to server

I have spent the last couple of hours battling to write some javascript and jquery.
Basically I am trying to loop through a table checking if an attribute exists within a TD if it does add its info into an array and post it back to the server
My code (I am sure it could be better)
$("#save-changes").click(function () {
var param = [];
var table = $("#products-grid > .t-grid-content > table tbody tr").each(function (i) {
//find checkboxes using class
var td = ($(this).find("td:nth-child(2)").find(".cb"));
var attr = $(td).attr('data-item');
if (typeof attr !== 'undefined' && attr !== false) {
console.log(td);
param.push({ "itemId": attr, "productId": td.val() });
}
});
console.log(param);
$.ajax({
url: '#Url.Action("ApplyProduct")',
data: param,
type: 'POST',
success: function (e) {
I am now stuck on trying to pass the array back to the server. What do I need to do to send the data back to the server as a parameter the server can understand?
Any help would be great!
add two parameters
dataType: "json",
data: JSON.stringify(param)
to your .ajax call.
Crate an object server side which has two int properties int called itemId and productId and then create a JsonResult route that takes an array of your object that you post too (this would be ApplyProduct in your case).
you cannot send arrays to a server , they have to be strings.
you could join the array together like this
param.join(";");
that would create a string with each value seperated by a ;
also you need to specify the data option as a key-value json
$.ajax({
url: '#Url.Action("ApplyProduct")',
data: {
param : param
},
type: 'POST',
then on the serverside you can split the string back into an array
$param = explode(";",$_POST['param']);

Can't send complex json data to server using prototype and rails

I'm trying to send the following data to the server but at the server side I don't see the json parameter that I'm sending. Can anyone tell me what I'm doing wrong?
Below you can see the code.
Prototype:
send_data_url = "change"
hash = $H({"blocks": [{"h": "2", "area": [{"width": "96%", "els": [{"title": "first", "mand": true}, {"title": "second", "mand": false}]}]}]});
var request_array_json = hash.toJSON();
new Ajax.Request(send_data_url, {
method: 'post',
parameters: request_array_json,
contentType: 'application/json;'
});
Rails:
def change()
debugger
my_json = ActiveSupport::JSON.decode(params["_json"])
end
In the controller I see that the params object does not have the json parameter.
It only shows the action and the controller:
{"action"=>"change", "id"=>nil, "controller"=>"default/test"}
Note: I'm using prototype 1.6 qnd rails 2.3.2.
I found a solution using a plugin called json_request.
To get this working nicely, I also wrapped Ajax.Request with a new class that can send complex JSON objects. Example code:
Ajax.JSON = Class.create(Ajax.Request, {
initialize: function($super, url, options) {
options = options || {};
options.contentType = ‘application/x-www-form-urlencoded’;
options.postBody = Object.toJSON(options.object);
$super(url, options);
}
});
new Ajax.JSON(url, { object: myObject });
Read more: http://labnotes.org/2007/12/11/json_request-handling-json-request-in-rails-20/comment-page-1/#comment-143190#ixzz0n5iKnO60

Resources