fetchRelated not fetching related - javascript

Been trying to get this up and running for a while now.
Basically i have a rest api as backend that returns json, all fine.
The problem i have is with backbone-relational. I'm sure i've just got something
wrong but i've been searching the nets for a while and couldn't find anything to help.
I'm trying to get a has many relationship between the model "Profession" and "Weapon".
Here's my code for that:
Profession = Backbone.RelationalModel.extend({
urlRoot: '../api/professions',
relations: [{
type: Backbone.HasMany,
key: 'weapons',
relatedModel: 'Weapon',
collectionType: 'Weapons',
reverseRelation: {
key: 'profession',
includeInJSON: 'id',
keySource: 'profession_id'
}
}]
});
Weapon = Backbone.RelationalModel.extend({
urlRoot: '../api/weapons'
});
Weapons = Backbone.Collection.extend({
model: Weapon,
url: function(models){
return '../api/weapons';
}
});
And a call to those api endpoints returns:
{name: "Profession1", id: 1}
[{name: "Weapon1", profession_id: 1}, {name: "Weapon2", profession_id: 1}]
So, if i understand correctly a profession.fetchRelated('weapons') should send an httprequest to the url for the weapons collection and pull the object which have a profession_id of 1. But nothing happens when i run profession.fetchRelated('weapons')

So, if i understand correctly a profession.fetchRelated('weapons') should send an httprequest to the url for the weapons collection and pull the object which have a profession_id of 1. But nothing happens when i run profession.fetchRelated('weapons')
This is not how I understand Backbone-relational to work - with the caveat that I'm working with an older version, and have not yet investigated the latest versions.
From my understanding, Backbone-relational wants data that looks different from your API responses.
I think that Backbone-relational wants references to nested models in the parent model response, either fully nested:
{
name: "Profession1",
id: 1,
weapons: [
{name: "Weapon1", profession_id: 1},
{name: "Weapon2", profession_id: 1}
]
}
In which case, it will fully populate the nested models.
Or, as references:
{
name: "Profession1",
id: 1,
weapons: ['weapon1','weapon2']
}
In which case Backbone-relational will stash the related keys internally, but present an empty collection. You would then use fetchRelated to fetch the full data for the related models:
assassin.fetchRelated('weapons')
Which make a request for weapons with id 'weapon1' and 'weapon2', either as individual requests, or if your API accepts a set request, a single request, expecting a response something like:
{id: 'weapon1', name: "Weapon1", profession_id: 1}
I don't, off the top of my head, know if there's a quick, built-in way to work with your API responses, other then to write a custom function.

To add to what Edward wrote, here's how you can get fetchRelated to work. First, as Edward claimed, fetchRelated will return nothing if your API already nests the data in the JSON response. So, if in Django-Tastypie you have your resource set up to use full=True:
movies = fields.ToManyField('movie.api.MovieResource', 'user', full=True)
then something like,
myuser.fetchRelated("movies")
will return nothing because the related data will already be included in the JSON response. But where fetch related is particularly useful is when you are attempting to do some lazy loading. So, if you have full=False in your Django-Tastypie field, and your JSON response only includes the id's and resource URI to that entry, you can use fetchRelated to actually populate that data.
myuser = new User({id: 1})
myuser.fetch()
myuser.fetchRelated("movies")
And now you have access to the related movies collection. If you're also using the Tastypie-Backbone plugin, you don't need to worry about constructing a special URL return statement in the Collection. It does it all for you using the tastypie select syntax of /2;3;7

Related

Combine objects into new object as json for post for web api request

I am using Angular 4 with Typescript and ASP Core with C#. I am trying to combine objects together before calling a post to my web api. Currently I have two objects with values that I want to post as one object.
Let say I have two interfaces
export interface Student {
name: string;
}
export interface Teacher {
name: string;
}
And I wanted my json in my body of the post to look like this as my ASP Core is expecting this as a parameter to the web api request.
{
"StudentName": "John Doe",
"TeacherName": "Jane Doe"
}
I am using the following to create the json for the body but this puts it into two separate records in the json. This also does not allow me to select specific properties if my interfaces had more than what the request required.
const body = JSON.stringify({ student, teacher });
Next I tried to access only the specific member variables in the JSON.stringify method, but for some reason it does not work. In addition, if this even worked it would end up with two properties with the same name.
const body = JSON.stringify({ student.name, teacher.name });
I am not sure if this is a typescript, javascript or angular issue. I tried searching online for some help but I don't think I am using the right keywords.
Thanks in advance!
The problem is that you're not labeling your object items:
const body = JSON.stringify({ StudentName: student.name, TeacherName: teacher.name })
is the expected format.

How to handle model / API response translation in AngularJS?

I have an angular application that requests data from a JSON API. A sample API response might be:
{
id: 1,
name: 'JJ',
houseId: 2
}
In my angular application I will have models representing a User, which also has a reference to a House object:
{
id: 1,
firstName: 'JJ',
surname: '',
house: {
id: 2,
address: 'XXX'
}
}
The application model and API responses differ in that there is one field for the name in the API response, but two in my application model. Is there an 'angular' way I can do some transformation from an API call response object to my application model to ensure that I am always dealing with consistent objects in my controllers/services?
Related to this, the API responds with the database id of the house object associated with that user, and not with the full house object included in the JSON. Is there a way to set my object up to automatically resolve this when needed?
As an example, I would like to display this user, with his address. If the object was fully resolved I could use 'user.house.address'. However, using the plain JSON response object, this would be undefined. Instead of having to explicitly resolve the house object by using the house API with the houseId, I would like this to happen 'behind the scenes' by previously stating how such an id would be resolved if the object is accessed.
Or am I approaching this the wrong way and the API response should be used to dictate the data structure of my application and explicit lookups via object id's is the preferred way?

Angular $resource save an object containing arrays

Let's say we have a Person $resource that looks like this:
$scope.person = {
name: 'Max',
friends: [1, 2, 3]
}
If we Person.save($scope.person) to server, it would send the following parameters:
name: 'Max'
friends: '1'
friends: '2'
friends: '3'
So I will not have access to the array of friends on the server. Only its last element would be accessible.
What is the correct way of saving objects containing arrays to server using $resource?
p.s. I'm aware of a really hacky way, which is renaming friends attribute to friends[], but that's not solving my problem, as I have a lot of these and I can't go with redefining properties back and forth
From documentation:
non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
So you have to use:
Person.save(null, $scope.person)
(first argument is object with url params, second is data to send)
Then your friends array will be available in request body.
Note also that if you have person resource, you can do:
var person = $resource(...);
person.name = 'john';
person.friends = ['friend1' ,'friend2'];
person.$save();

Emberjs Deep Model Associations not available in templates

I'm new to Emberjs, and I'm trying to get my head around how to get data out of my model.
Here's the data structure as its being returned from my server
candidate: {
image: [image],
user: {
name: [User Name]
},
agent: {
phone: [phone]
team: {
name: [Team Name]
}
user: {
name: [User Name]
}
}
}
I cant get ember to recognize any associations more than one level deep.
heres my candidate controller
App.CandidateController = Ember.ObjectController.extend({
location: function() {
var address = this.get('address');
var city = this.get('city');
var state = this.get('state');
var zip = this.get('zip');
return address + ' ' + city + ' ' + state + ', ' + zip;
}.property('address', 'city', 'state', 'zip')
});
App.CandidateSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
agent: {embedded: 'always'},
user: {embedded: 'always'}
}
});
This allows me to get one level deep, but I need two or three levels of association.
Is there a different way to go about it?
I thought organizing everything on the server the way I want it displayed, and just returning the data as its supposed to be rendered to ember, but I have a feeling I'll run into problems when trying to update the models.
Any help is appreciated.
/****** UPDATE *******/
I have refactored my code and I am now returning data from the serializer like this:
{
candidate: {
// relevant fields
},
agent: {
//relevant fields
},
team: {
// relevant fields
}
user: [
{ // candidate user fields },
{ // agent user fields }
]
};
However, data is still not available in my template. In the Ember chrome extension, in the data tab, I get
candidate: (1)
agent: (0)
team: (0)
user (2)
I can see candidate and user data, but not agent or team data. In my candidate model, I have:
App.Candidate = DS.Model.extend({
// other fields
user_id: DS.attr('number'),
agent_id: DS.attr('number'),
user: DS.belongsTo('user'),
agent: DS.belongsTo('agent')
});
It doesn't seem like the belongsTo association actually does anything.
So the first issue is that I'm not getting the correct data, the second issue, and the one that makes me think I am going about this incorrectly, is that I have two users information that I need to display in the template. The first is user information associated with the candidate, and the second is user information that is associated with the agent. Both data need to appear in the same template. Since there is no hierarchy to the data, how would the template know which user info to display in each location?
Again, I think Im thinking about this whole thing incorrectly.
Thanks for your help.
Ember data expects models in a JSON response to be flat, and it's the job of the Serializer to transform your server response into that format. Associations usually are done by ids. The second level is not working because Ember needs to turn each level into an Ember.Object in order to observe property changes.
It might help to look over the JSON conventions portion of the guides. You can also plug your models into the ember data model maker and see what your responses should look like. Finally, make sure you're using the ember-inspector Chrome extension. When I am debugging ember-data related issues, it's usually easiest to just stop after the model hook returns, look in the inspector's store tab, and examine what data has been loaded.

Using mongojs and node.js, how to find documents using multiple attributes as criteria

I am trying to use the find method to return documents that meet multiple criteria like so:
db.issues.find({ 'title.name': name, 'title.year': year, 'title.publisher': publisher }, function(err, issues) { ...
I get an empty array back as a result.
If I try the same query directly in the mongodb console, I get the results back as expected.
In mongojs, I am able to retrieve results if I only supply one attribute, like so:
db.issues.find({ 'title.name': name }, function(err, issues) { ...
So, how do I perform a search using multiple attributes? Do I need to use a different method?
UPDATED 2/2/2014 7:56
The issue schema is as follows:
{
title: { name: 'Some title name', year: 1999, publisher: 'Some publisher' },
number: "122",
variant: null,
print: "1",
year: "1999",
certification: { type: "Some certification", grade: 10 },
url: "http://www.someurl.com",
sales: []
}
There is no difference in how mongojs handles queries as it's intention is to mimic ( somewhat ) the behavior of the mongo shell.
Are you sure your criteria actually returns something? As it stands you possibly have an issue there. If you still cannot diagnose this, post up the result you expect to get and some of your schema as an edit. Don't forget to check your var's that numbers aren't strings and vice versa.

Categories