Scopes in model relations - strongloop api
j0n47h4n opened this issue · comments
I found in the documentation that scopes enable you to specify commonly-used queries that you can reference as method calls on a model. Below i have a category
model. I am trying to create scopes that apply to the relation. Unfortunately the below does nothing. How can I get scopes to apply to relation as shown below?
GET /Categories/{id}/games
- This gets all games
I tried to modify the model: common/models/category.json
"relations": {
"categories": {
"type": "hasMany",
"model": "Categories",
"foreignKey": "",
"scopes": {
"mature": {"where": {"mature": true}},
"sports": {"where": {"sports": true}},
}
}
},
I want to be able to get the data through endpoing: /Categories/{id}/games/mature
Table schema:
catgories
category_name category_id
------------- -----------
fighting 1001
racing 1002
sports 1003
games
game_name category_id mature
------------ ----------- --------------
Tekken 10001 true
Forza 10002 false
hey @j0n47h4n Do you have to use categories/{id}/games/mature
as the endpoint?
If not, according to your description, I uploaded my solution to sandbox.
I think first you need to create a hasMany
relation from category
to game
, not from category
to itself (maybe it's a typo in your code? :) ). And don't forget to establish belongsTo
relation from game
to category
as well.
In file /server/boot/sample.js
I showed how to create the instances and query, in my solution,
you can either use
Game.find({
"where": {
categoryId: 1,
mature: true
}
}, function(err, result) {
//TODO
}
}
in .js code
or
use endpoint
/api/categories/1/games?filter[where][mature]=true
in browser to get the result.
Does my solution help? Let's solve it together if you have any further questions, thanks!
Hey @jannyHou, thanks for your assistance. You are right it was typo there is a hasMany
relation from category
to game
. Ok I tried your solution but Yes, I am looking to use categories/{id}/games/mature
as the endpoint. I really dont want to expose the query in the end point like /api/categories/1/games?filter[where][mature]=true
@jannyHou Any thoughts/ideas how to implement end point categories/{id}/games/mature
?
hey @j0n47h4n we don’t expose the 2nd level (related) scope over REST right now, so your expected endpoint is not supported yet. But we will mark it as a feature, and thank for your suggestion!
@jannyHou hmm there are 156 open issues with the features tag and 24 closed. So I am guessing that it will be a long while before that gets implemented.
@j0n47h4n There are probably more open issues than that! ;p More like 500+ issues. Anyways, we get around to issues whenever we have time. If you need priority support, see https://strongloop.com/node-js/subscription-plans/ for subscription plan pricing. In addition, feel free to send us a message at callback@strongloop.com with your specific needs and they can answer any other questions you may have there.
So you want to list every category containing at least one game rated as mature?
Or is it, for each of the above, include matching games?
Hi @amenadiel, List all games under a certain category that are mature
. For Example, I want to get all the games rated mature
for games under category fighting
, Endpoint would be categories/1001/games/mature
In that case I'd add a remote method to game.js
Game.mature = function(id_category, cb) {
Game.find({
"where": {
categoryId: id_category,
mature: true
}
}, function(err, results) {
cb(err, results);
});
};
Game.remoteMethod('mature', {
accepts: [{
arg: 'id_category',
type: 'number'
}],
returns: {
arg: 'data',
type: 'object',
root: true
},
http: {
path: '/mature/:id_category',
verb: 'get'
},
description: 'Lists mature games for a given category'
});
So the endpoint would be /games/mature/{{id_category}}'
Thanks @amenadiel close to what I want but not quite. For anyone trying to achieve the same goal, currently it can only be done using Remote Methods as mentioned above.
Added the remote methods to common/models/category.js
module.exports = function(Category) {
Category.mature = function(id, callback) {
var app = this.app;
var Game = app.models.Game;
Game.find({
"where": {
categoryId: id,
mature: true
}
}, function(err, gameArr) {
if (err) return callback(err);
console.log(gameArr);
callback(null, gameArr);
});
}
Category.remoteMethod(
'mature', {
accepts: [{
arg: 'id',
type: 'number',
required: true
}],
// mixing ':id' into the rest url allows $owner to be determined and used for access control
http: {
path: '/:id/games/mature',
verb: 'get'
},
returns: {
arg: 'games',
type: 'array'
}
}
);
};
Add the ACL property common/models/category.json
.
.....
.....
"acls": [
{
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW",
"property": "mature"
}
]
Now I am able to get all games that are mature
by get method: http://0.0.0.0:3000/api/categories/:id/games/mature
Hey @j0n47h4n
In your example you access Game model within the category.js by doing:
module.exports = function(Category) {
Category.mature = function(id, callback) {
var app = this.app;
var Game = app.models.Game;
.
.
.
}
}
However when I try to do the same thing receive the following error:
TypeError: Cannot read property 'app' of undefined
So my question is: what is the right way to access to a model (in this case Game) within another model's (in this case Category ) .js file?
UPDATE:
Found the answer to my question here: #1213
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS
file at the top-level of this repository.