emberjs hasMany returns undefined - javascript

I'm trying to implement a minimal emberJs app using fixtures and a one-to-many relation between two models:
App.store = DS.Store.create({
revision: 11,
adapter: 'DS.FixtureAdapter'
});
App.Album = DS.Model.extend({
Name: DS.attr("string"),
Songs: DS.hasMany('App.Song')
});
App.Song = DS.Model.extend({
Name: DS.attr("string"),
Album: DS.belongsTo('App.Album')
});
App.Album.FIXTURES = [
{
id: 1,
Name: 'foo'
},
{
id: 2,
Name: 'bar'
}
];
App.Song.FIXTURES = [
{
id: 1,
Album_id: 1,
Name: "asdf"
},
{
id: 2,
Album_id: 2,
Name: "Test"
}
];
I can access the Album model through the console like this
App.Album.find(1).get('Name') # => foo
Whenever I try access the Songs property trough the relation between album and song I get undefined:
App.Album.find(1).get('Songs').objectAt(0) # undefined
Any hints what I might be doing wrong here?

You haven't defined which Songs an Album has. You need to specify Songs: [1,2,3] in your Album model.
(Quite sure it's Songs, but it may Song_ids.)

Related

Sequelize, how structuring return value inside single object

Sorry for my bad English. I have used fastify for my javascript framework and Postgresql as my database and sequelize as my ORM. But problem occured when i have multiple models.
This is my Code :
// Extract Db
const { student} = this.models
return student.findById(id, {
include: [
{ all: true },
],
limit: 1,
})
The result is :
// Result
{
id: 1,
name: "my beastiful name",
class: "...",
...
// School Object
school: {
id: 23,
name: "My School name",
...
}
}
But what i want is :
// Result
{
// Student Object
student: {
id: 1,
name: "my beastiful name",
class: "...",
...
},
// School Object
school: {
id: 23,
name: "My School name",
...
}
}
Should i use multiple "find" to achive this result.

How to query sequelize model by association, but include all associated objects?

Trying to query by all association's attribute, but get all associations
# FAQs: { id: 1, name: 'How to do it?' }, { id: 2, name: 'How to FIX it?' }
# tags: { id: 1, slug: 'api' }, { id: 2, slug: 'beta' }
# taggings: { id: 1, faqId: 1, mainEntityId: 1, mainEntityType: 'faq' }, { id: 2, faqId: 1, mainEntityId: 2, mainEntityType: 'faq' }
const query = { slugs: ['api'] }
const foundFAQs = await this.models.FAQ.findAll({
where: {
'$taggings.tag.slug$': { $in: query.slugs },
},
include: [{
model: this.models.Tagging,
as: "taggings",
include: [{
model: this.models.Tag,
as: 'tag',
}],
}],
})
My model definition:
models.Tagging.belongsTo(models.Tag, { as: 'tag', onDelete: 'cascade' });
models.Tag.hasMany(models.Tagging, { as: 'taggings', onDelete: 'cascade' });
models.Tag.belongsToMany(models.FAQ, { through: models.Tagging, as: 'faqs' });
models.FAQ.hasMany(models.Tagging, { as: 'taggings', onDelete: 'cascade' });
models.FAQ.belongsToMany(models.Tag, { through: models.Tagging, as: 'tags' });
What do you expect to happen?
I want to get all FAQs what has associated TAG api and have all its tags.
Object:
{
id: 1,
name: 'How to do it?',
tags: [
{ id: 1, slug: 'api' },
{ id: 2, slug: 'beta' }
]
}
What is actually happening?
Query returns object:
{
id: 1,
name: 'How to do it?',
tags: [
{ id: 1, slug: 'api' }
]
}
Output
SELECT \"faq\".\"id\", \"faq\".\"name\", \"faq\".\"bankId\", \"faq\".\"priority\",
\"faq\".\"publishedLocales\", \"faq\".\"createdAt\", \"faq\".\"updatedAt\", \"taggings\".\"id\"
AS \"taggings.id\", \"taggings\".\"tagId\" AS \"taggings.tagId\", \"taggings\".\"locked\"
AS \"taggings.locked\", \"taggings\".\"sdkId\" AS \"taggings.sdkId\", \"taggings\".\"guideId\"
AS \"taggings.guideId\", \"taggings\".\"newsId\" AS \"taggings.newsId\", \"taggings\".\"faqId\"
AS \"taggings.faqId\", \"taggings\".\"apiId\" AS \"taggings.apiId\", \"taggings\".\"createdAt\"
AS \"taggings.createdAt\", \"taggings\".\"updatedAt\" AS \"taggings.updatedAt\", \"taggings->tag\".\"id\"
AS \"taggings.tag.id\", \"taggings->tag\".\"name\" AS \"taggings.tag.name\", \"taggings->tag\".\"slug\"
AS \"taggings.tag.slug\", \"taggings->tag\".\"tagType\" AS \"taggings.tag.tagType\", \"taggings->tag\".\"mainEntityId\"
AS \"taggings.tag.mainEntityId\", \"taggings->tag\".\"createdAt\"
AS \"taggings.tag.createdAt\", \"taggings->tag\".\"updatedAt\"
AS \"taggings.tag.updatedAt\" FROM \"faqs\" AS \"faq\" INNER JOIN \"taggings\"
AS \"taggings\" ON \"faq\".\"id\" = \"taggings\".\"faqId\" LEFT OUTER JOIN \"tags\"
AS \"taggings->tag\" ON \"taggings\".\"tagId\" = \"taggings->tag\".\"id\" WHERE \"faq\".\"bankId\" = 'bank.csas'
AND \"taggings->tag\".\"slug\" IN ('faq') ORDER BY \"faq\".\"priority\" DESC;
Dialect: postgres
Dialect version: pg#^6.1.0
Database version: PostgreSQL 10.1
Sequelize version: 4.23.2
Tested with the latest release: No (4.23.2)
Node: 8.6.0
I am not sure if it is a bug or I'm doing something wrong.
Thanks
You're looking to include all related data for each record, but filter those records on that related data. You're going to want to get Sequelize to generate SQL similar to:
SELECT "faq"."id", ....
FROM "faqs" AS "faq"
INNER JOIN "taggings" AS "taggings" ON "faq"."id" = "taggings"."faqId"
LEFT OUTER JOIN "tags" AS "taggings->tag" ON "taggings"."tagId" = "taggings->tag"."id"
LEFT OUTER JOIN "tags" AS "taggings->tagdata" ON "taggings"."tagId" = "taggings->tagdata"."id"
WHERE "faq"."bankId" = 'bank.csas' AND "taggings->tag"."slug" IN ('faq')
ORDER BY "faq"."priority" DESC;
Something like this might work:
const foundFAQs = await this.models.FAQ.findAll({
where: {
'$taggings.tag.slug$': { $in: query.slugs },
},
include: [{
model: this.models.Tagging,
as: "taggings",
include: [{
model: this.models.Tag,
as: 'tag',
},{
model: this.models.Tag,
as: 'tagdata',
}],
}],
})
The idea here is that you're performing a join on which you are filtering, and then another join to get the extra records for the filtered rows.
This worked for me today -- nested includes:
getReferralPlanForThisCode(parent, args, context) {
let {referralCode} = args;
return Promise.resolve()
.then(() => {
let referralPlan = connectors.ReferralPlans.findAll({
include: [{
model: connectors.ReferralCodes,
where: {unique_referral_code: referralCode},
include: [{
model: connectors.epUserData, as: 'referrer',
}],
}],
})
return referralPlan;
})
.then(referralPlan => {
return referralPlan;
})
.catch((err) => {
console.log(err);
});
}

How to add a nested List of objects in Realm "Error: JS value must be of type: object"

I'm trying to create Realm database that has a json array of objects with a nested array of objects.
When I try to add using the code below I always get the error: JS value must be of type: object.
Schemas:
import Realm from 'realm';
class Exercise extends Realm.Object {
}
Exercise.schema = {
name: 'Exercise',
primaryKey: 'id',
properties: {
id: 'int',
name: 'string',
category: 'string',
bodyPart: 'string',
levels: {type: 'list', objectType: 'Level'}
}
};
class Level extends Realm.Object {
}
Level.schema = {
name: 'Level',
properties: {
level: 'int',
equipments: 'string'
}
};
export default new Realm({schema: [Exercise, Level, Multiplier]});
and the method where I'm trying to create the database:
realm.write(() => {
let exercise = realm.create('Exercise', {
id: 209,
name: 'Dumbbell Overhead Press',
category: 'Military Press',
bodyPart: 'Shoulder'
}, true);
exercise.levels.push({
level: 3,
equipments: 'DB'
});
});
I tried every way possible, putting the array direct in the Exercise creation, etc, I had no success..
Cheers
U have to specify the index of the record. As exercise.returns a record not an exercise object
try this instead
realm.write(() => {
let exercise = realm.create('Exercise', {
id: 209,
name: 'Dumbbell Overhead Press',
category: 'Military Press',
bodyPart: 'Shoulder'
}, true);
exercise[0].levels.push({
level: 3,
equipments: 'DB'
});
});

SEQUELIZE - How to Get All Assosciated Objects?

I have a many to many association like this:
Squad.belongsToMany(Member, {through: Membership});
Member.belongsToMany(Squad, {through: Membership});
How do I find all the Squads, and for each squad, show me the squad name and an array with the Members that each squad has associated with it?
UPDATED WITH WHAT I'VE BEEN TRYING AND WHAT RESULTS I GET:
I've been trying things like this:
Squad.findAll({
include: [{
model: Member,
required: true
}]
}).then(squads => {
// The rest of your logics here...
});
Here's a sample of what I get:
{ id: 3,
name: 'Knicks',
city: 'NYC',
state: 'NY',
'members.id': 3,
'members.name': 'Carmelo',
'members.city': 'NYC'
},
{ id: 3,
name: 'Knicks',
city: 'NYC',
state: 'NY',
'members.id': 2,
'members.name': 'Penny',
'members.city': 'Orlando',
'members.state': 'Florida'
}
But what I want is not multiples of the same object and individual member info. I'm trying to get something more like this:
{
id: 2,
name: 'Lakers',
members: [ memberInfo, memberInfo, memberInfo]
}
Is there a way to do that?
Assuming that you modeled your relations correctly, then you should be able to do something like
Squad.findAll({
include: [{
model: Member,
required: true
}]
}).then(squads => {
// The rest of your logics here...
});

Reading out members of a related model in a controller

I have two models in a relationship.
Level
App.Level = DS.Model.extend({
title: DS.attr(),
description: DS.attr(),
results: DS.hasMany('levelresult', {
async: true
})
});
App.Level.FIXTURES = [{
id: 1,
title: "Lorem Ipsum",
description: "Lorem Ipsum dollor sit amet",
results: [100,101]
}];
and Levelresult
App.Levelresult = DS.Model.extend({
minutes: DS.attr('number'),
seconds: DS.attr('number'),
points: DS.attr('number'),
failures: DS.attr('number'),
level: DS.belongsTo('level')
});
App.Levelresult.FIXTURES = [{
id: 100,
minutes: 44,
seconds: 23,
points: 7,
failures: 0,
level: 1
}, {
id: 101,
minutes: 12,
seconds: 33,
points: 4,
failures: 22,
level: 1
}];
So I declared a route for the parent(-resource)-template like this:
App.LevelRoute = Ember.Route.extend({
model: function (params) {
return this.store.find('level', params.level_id);
}
});
Its easy to work with them into the level/result-template. Even the related model (as a member of the Level-Model) Levelresult is available within the template (e.a. {{#each result in results}}).
Now I want to pick just a single entry out of the related Levelresult's (e.a. "101").
But in the nested route CONTROLLER (level/result as said before) I cant read any member except "id"
App.LevelResultController = Ember.ArrayController.extend({
getBestResult: function() {
var results = this.get('results');
results.forEach(function(result) {
console.log(result.get('id')); //Output: "100" and "101" --> correct
console.log(result.get('minutes')); //Output: "Undefined" and "Undefined" --> WHY?
}
//... Pick out the best one ...
}.property('results')
});
I don't get it, why reading "id" simply works but other members wont.

Categories