TypeORM relationship: Only IDs instead of whole instances - foreign-keys

According to the documentation, in TypeORM a relationship is defined as follows:
A user has exactly one profile.
import {Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn} from "typeorm";
import {Profile} from "./Profile";
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column()
name: string;
#OneToOne(type => Profile)
#JoinColumn()
profile: Profile;
}
Issue
When creating a new user, why do I have to pass a complete instance of the entity (profile: Profile) instead of - as usual - only one ID? Like this:
#OneToOne(type => Profile)
#JoinColumn()
profileId: number;
Isn't there another way?
This procedure causes a large, unnecessary overhead, if you have to make 4 queries for 4 foreign keys to get the corresponding instance instead of the ID.
I would be very grateful for help to get around this!

In TypeORM the navigation field (here profile) can be combined with the plain foreign key field (profileId). So you can write:
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column()
name: string;
#OneToOne(type => Profile)
#JoinColumn()
profile: Profile;
#Column()
profileId: number;
}
Then it's up to you if you update the relation with the entity object or only with the profile id.

Related

How to retrieve the same model from another REST url in EmberJS

The models tree of my emberJS app match the tree of my API however, I have 2 different routes returning the same type of data :
/products/ and /users/:id/supported_products/ both return products data.
When I need to have the products of the app there is no problem :
this.store.query('product',params);
However I am not sure how to query products from the user path. The place to do so would be the adapter, but I need to define a secondary adapter that I would call when I need supported products,and I have no idea how to do so.
I think if it were me I would create a virtual query parameter that would instruct a custom adapter on how to change the endpoint on the fly.
For example I might have a supportedByUser flag. Then in my app/adapters/product.js do something like this:
import JSONAPIAdapter from 'ember-data/adapters/json-api';
export default JSONAPIAdapter.extend({
urlForQuery(query, modelName) {
let userId = query.supportedByUser;
delete query.supportedByUser;
return userId
? `${this.namespace || ''}/users/${userId}/supported_products`
: this._super(...arguments);
}
});
Here is an example twiddle demoing this: https://ember-twiddle.com/b406391e98ed4fda30bc227a894fa7c9

Find the class name of a relation from the instance of a model in ember JS

I have foo an instance of the ember-data model thing. thing.js has the following property :
owner: DS.belongsTo('user')
If I have foo with an empty owner, how can I, with only foo and the 'owner' string, retrieve the value 'user' representing the model of the owner relation?
EDIT: I want to allow my select-relation component to works with relations where the name is different from the class name
It sounds like you have some work to do to finish setting up your relationships. Have a read through this page of the guides.
If the relationships are set up correctly, to get the associated user, you should be able to do foo.owner. This assumes that users are already present in the store. I recommend using the Ember Inspector browser plugin to debug the relationships.
This looks like a use case for typeForRelationship.
In your example you should be able to do something like
store.modelFor('thing').typeForRelationship('owner', store);
If you don't like that approach you can use the belongsTo reference API, where you use the meta data from the relationship to get the type
foo.belongsTo('owner').type
The only thing with that approach is that the type property may not be public API and possible (though unlikely) to change at some point.
It seems I can do the following :
this.get('model').get('_internalModel._relationships.initializedRelationships.'+this.get('relation')+'.relationshipMeta.type')
model being an instance and relation the string of the relation name, it correctly return the model of the relation.
EDIT : a better solution not using private API courtesy from the ember discord :
function getRelatedModelName(record, relationName){
let ParentModelClass = record.constructor;
let meta = get(ParentModelClass, 'relationshipsByName').get(relationName);
return meta.type;
}

Associating multiple items with a single REST call

I am using the Loopback framework, and have modelA which is in a many-to-many relation with modelB.
I want to know if it's possible to relate multiple items from modelB to modelA.
There is currently a way to relate one item with this call:
/modelA/{id}/modelB/rel/{fk}
Is there any way to perform this in a bulk operation?
If I understand your question correctly, I think you can simply do it through a filter. ModelA has many modelBs, Let me assume the relation name is 'modelBs'
modelA.find({
where: [your filter option on model A]
include: {
relation: 'modelBs',
scope: {
[your filters on model B]
}
}
})
in restful way:
/modelAs?filter[include]=modelBs&filter[where]....
The official documentation may help: https://docs.strongloop.com/display/public/LB/Querying+data
It seems to be HasManyThrough model.
I believe your model names starts with lowercase but ideally it should be ModelA and ModelB and their instances can then be saved in modelA and modelB variables.
In order to use add method, you will need to first find instance of ModelA first using ModelA.findById which you can save in modelA variable and then use the following code:
modelA.modelBs.add(modelBFieldsObject, function(err, patient) {
...
});
where modelBs should be the name of relation in the ModalA.json file as in
"relations": {
"modelBs": {
"type": "hasMany",
"model": "ModelB",
"foreignKey": "modelAId",
"through": "ModelAModelB",
"keyThrough": "modelBId"
}
...
I think it should be allowed to pass an array of modelBFieldsObject to create multiple instances as in
modelA.modelBs.add([modelBFieldsObject, modelBFieldsObject], function(err, patient) {
...
});
Tip: For clarity, name your models beginning with upper case letter and their instance variable in camelCase format.
References: Methods added to the model.

adding models to backbone collections

I have a rails app with 4 Model classes, with multiple instances in each table. I have created backbone Model and Collection classes in CoffeeScript to match. I can successfully load all of the collections and can render them in views. So far, so good. Here is one of my collections, with its associated model:
class window.CoffeeWater.Collections.Histories extends Backbone.Collection
url: '/api/histories'
model: History
class window.CoffeeWater.Models.History extends Backbone.Model
I need to be able to create a History model object, and then add it to the Histories collection. The documentation states that I have to set a 'collection' property when creating my new model, in order for it to get the 'url' property from the collection. My problem is that I can't seem to set the 'collection' property value correctly, because the url property does not get set on the model instance
attributes = {'start_time': new Date (1434740259016), 'stop_time': new Date (1434740259016 +(86400*1000)), 'valve_id': 2}
options = { collection: window.CoffeeWater.Collections.Histories }
history = new window.CoffeeWater.Models.History(attributes, options)
window.CoffeeWater.Objects.Collections.Histories.add(history)
Inspecting the resulting 'history' object does not show the same attributes that exist in models already in the collection, and the url property is missing.
I am currently at a loss. Does anyone have an example on how to do this? The backbone.js docs do not show any relevant examples.
The way the url in model is defined like this.
If there is a url property in model.
class window.CoffeeWater.Models.History extends Backbone.Model
url:'/api/history/1'
Then when model.fetch(), it will call that url. If this property is not found, it will see if the associated collection does have a 'url'. You try to set this collection variable.
What you are missing is this. This
class window.CoffeeWater.Collections.Histories extends Backbone.Collection
is actually a definition of a class. It is not an object yet. You need to initialize it, like you do in java. so
var historyCollection=new window.CoffeeWater.Collections.Histories()
Now you have a collection object. When you do
historyCollection.add(history);
The "collection" of model is automatically set to the "historyCollection" object, which contains a 'url'. So in fact, you do not need to manually put this in the option.
basically
attributes = {'start_time': new Date (1434740259016), 'stop_time': new Date (1434740259016 +(86400*1000)), 'valve_id': 2}
var historyCollection=new window.CoffeeWater.Collections.Histories()
var history = new window.CoffeeWater.Models.History(attributes)
historyCollection.add(history)

Ember-Data: Ember does not make the connection between two related models - DS.ActiveModelAdapter

I am trying to retrieve a project which has a hasMany relationship to projectTeams which has a belongsTo relationship to Teams.
I am using ActiveModelAdapter and have followed the conventions indicated in the doc on emberjs.com. After the files have been retrieved, I checked the JSON output and it is valid according to what ember expects (foreign keys contain the _id suffix). However, the relationship between the models is not made.
Interesting fact though is that I can get a reference from ProjectTeam to both Project and Team...
For your convenience I created the following fiddle:
http://jsfiddle.net/alexspeller/SwWkB/1/
You need to define the project team ids on the json for projects
id: 1
name: "asd"
top_down_date: "2014-01-08"
cape_town_date: "2014-01-23"
created_at: "2014-01-04T16:17:59.441Z"
updated_at: "2014-01-04T16:17:59.441Z"
project_team_ids: [1]
http://jsfiddle.net/VHfKv/