Removing base model relations in Loopback 3 - loopbackjs

I'm having a little bit of trouble when attempting to remove relations
from a model that uses another custom model as its base. Assuming the following
setup
// Item Model, item.json
...
"relations": {
"parent": {"type": "belongsTo", "model": "Holder"}
}
...
// Special Item Model, item.json
...
"base": "Item",
"excludeBaseProperties": ["parentId"],
...
"relations": {}
...
When I look the Special Item model I find that the parentId still exists and
it even shows up in the relations.
What is the proper way to remove parent model relations from a child Model in loopback 3 ?

I felt a bit silly about posting the question now because I figured one way to solve it a little while after posting it.
I'm posting my solution here, would appreciate if anyone can review it:
Create a module called clear-relations.js
Use the following bit of code inside it -
'use strict';
module.exports = function(Model) {
// Get the attribute names of the inherited relations
// and then explicitly delete them
Object.keys(Model.settings.relations).forEach(relation => {
delete Model.settings.relations[relation];
});
}
If you don't already have a .js file for your model, create one then use the following bit of code
const ClearRelations = require("path/to/clear-relations.js");
module.exports = function(MyModel) {
ClearRelations(MyModel);
}
Seems pretty easy once I figured it out. Hope this helps someone.

Related

How to get Count value in a HasMany relationship when querying sub Models?

On a Category model I created, I have the following relation:
"subscriptions":
{
"type": "hasMany",
"model": "Subscription"
"foreignKey": "",
"options": { "nestRemoting": true } } }
How could I get the Count() result when running:
this.userService.getCategories(this.currentUser.id,
{include: {relation: 'subscriptions', scope: {type: 'count'}}})
.subscribe((data: any[]) => { this.categories = data };
I would like to count the number of subscription when getting the categories belonging to the user, in the same observable().
Like show above, I tried with the scope of type 'count'. nothing comes.
Thanks for any help.
As an answer:
Loopback provides the 'include' filter to be able to retrieve related models.
As a consequence an Observable is retrieved. It does contain the relationship.
Getting the Count() is as simple as writing {{category.subscriptions.length}}in the HTML.
Hope this helps.

Loopback Model with no datasource

I want to create a model in loopback with very complex logic, impossible to map to any datasource. SO I would like to somehow only generate the CRUD methods skeletons in JS and be able to simply override them, as explained here:
extend the CRUD method in LoopBack
From the outside it should be accessible as any REST API, with all the CRUDs and other methods, typical in loopback.
I would also apply ACLs, authorization and all the stuff to it, just as normal.
How should I proceed?
Is this case somewhere formally documented?
Are the CRUD methods officially documented, so I can safely override them?
You can create it with the lb model command. Be sure to select:
Datasource: (no datasource)
Model: Model
Expose: Yes
Common/server: Common
This will create the files inside common/models. You can do this manually too. A datasource-less model is essentially composed of these file contents:
test.json
{
"name": "test",
"base": "Model",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
test.js
'use strict';
module.exports = function(Test) {
Test.greet = function(msg, cb) {
cb(null, 'Greetings... ' + msg);
}
Test.remoteMethod('greet', {
accepts: { arg: 'msg', type: 'string' },
returns: { arg: 'greeting', type: 'string' }
});
};
This will create a route called /test, with a function named "greet".
The loopback node API is documented there.
Just override the methods like in the link you provided. You will need to match the node API of the original method in your overriden method, but apart from that no restrictions. ACLs are decoupled from that so nothing to worry on this side.
However, I don't know how you plan to write a stateless loopback application without using a datasource, since this is where the state is stored. If your loopback application is not stateless, remember that it will not scale (cannot start multiple instances in a cluster), and will do nasty things when it will crash. Can't you just split your problem / simplify it ?

ObjectAt(0) doesn't work with Ember.Controller

I'm trying to upgrade my Ember application to the latest Ember 1.13.2 and therefore am trying to replace all Ember.ArrayController with Ember.Controller.
I've got a problem with the category-controller of my blog. The data retrieved from my server looks like this:
"posts": [
{
"category": {
"id": "1",
"name": "tech"}
"title": "my title",
"body": "post-content",
"isPublished": true,
},
...
]
In my category-controller I need both, the category-id and the category-name.
With the Ember.ArrayController I used objectAt(0) to get both from the first post loaded in the model for that purpose but this doesn't work with Ember.Controller anymore.
How can I get these two attributes in my controller?
This code doesn't work anymore:
breadCrumb: function(){
return this.objectAt(0).get('category').get('name');
}.property('model.[]'),
categoryId: function(){
return this.objectAt(0).get('category').get('id');
}.property('model.[]'),
You just get it from the model directly instead of using the proxy behavior:
return this.get('model').objectAt(0).get('category').get('name');
Or, if you like shorthand:
return this.get('model.firstObject.category.name');
EDIT: While I'm at it, you could also declare these as aliases:
breadCrumb: Ember.computed.alias('model.firstObject.category.name'),
If you don't do that, you should probably change your dependent key. Your property won't update if the nested properties change. You need to use something like model.firstObject.category.name or model.#each.category.name.

Loopback 2.4: how to query certain fields of related model via REST API

I have User model over relational DB.
Each User can hasMany "users" where "chiefId" is FK.
"relations": {
"users": {
"type": "hasMany",
"model": "User",
"foreignKey": "chiefId"
},
}
I can query related users for each chief-user like this:
GET /users?filter={"include":"users"}
But it returns full user objects.
How should I query only "name" properties of related users?
Also is it possible to count related instances in one request to server?
A late reply but I just ran into this question now. It is possible:
filter: {
include:{
relation: "users",
scope: {
fields:["name"]
}
}
}
As far as I understood this question is about adding a nested filter on an include level, which seems to be not yet supported: https://groups.google.com/forum/#!msg/loopbackjs/T6onsYMJFOI/V4ILc3Obf3MJ
May be it's not the best way to approach this problem, but what you can do is a manual response transformation in .afterRemote('find', ...) hook.
/users?filter[fields][0]=name
See https://github.com/strongloop/loopback-example-relations-basic for more info.

How to access complex nested json in ember.js

after thorough searching stackoverflow and reading through all of the documetation on emberjs.com I'm finding myself stuck. I have a complex json object that I'm trying to model and output in my ember project.
I don't have control over the JSON, otherwise I'd change it's format to be easier digested. That said, here is my problem.
I have the following json
[
{
"id":1,
"catId": "10051",
"catUrl": "path/to/location",
"childCount": "4",
"description": [{
"text": "Description Text"
}],
"identifier": "UNQ123456",
"partialResults": "false"
}
]
What I'm trying to get at is the text value in description. I've tried creating the hasMany and belongsTo nested model construct described on emberjs.com, as well as many other patterns that were described as answers here on stack overflow, yet none of them seem to work or match the data construct I have to work with.
I've even tried the anonymous function in the first block of code on this page. http://emberjs.com/guides/models/defining-models/ trying to traverse this to the text that I want.
Regardless, any help would be much appreciated.
You could define a custom data transform to handle your special JSON field. This can be done by using the DS.RESTAdapter.registerTransform function. Something like this should work for your use case:
DS.RESTAdapter.registerTransform('descriptionText', {
serialize: function(data) {
var text = data[0].text;
return text;
},
deserialize: function(text) {
var data = [Ember.create({text: text})];
return data;
}
});
And then use it as a custom attribute for your model:
App.MyModel = DS.Model.extend({
...
description: DS.attr('descriptionText')
});
Note that the name of the transform could be something else as descriptionText as long you use the same name for DS.attr(...).
Hope it helps.