I have a model Parent that hasMany('children'). The Child model belongsTo('uncle').
Is there a way to include Uncle in the Parent response using serializers? Right now I have custom responses in my server config, but I'd rather move it out.
Parent
import { Model, hasMany } from 'ember-cli-mirage';
export default Model.extend({
children: hasMany('child'),
});
Child
import { Model, belongsTo } from 'ember-cli-mirage';
export default Model.extend({
parent: belongsTo({ polymorphic: true }),
uncle: belongsTo(),
});
Uncle is discovered from ember-data and has no defined relationships.
You can either include the Uncle by default using a child serializer
// mirage/serializers/child.js
export default Serializer.extend({
include: ['unclde']
});
or include it via the ?include query param from the client
GET /parents/1?include=children.uncle
Related
I'm using Nest's CLI Plugin to automatically annotate stuff for my documentation.
The issue is that Instead of loading only the entity imported by my module, the plugin also loads all the entities referenced in relations into Swagger UI.
For example my Cidades Module uses the following entity which has 3 relations:
#Index('cidades_pkey', ['idCidade'], { unique: true })
#Entity('cidades', { schema: 'public' })
export class Cidades {
#PrimaryGeneratedColumn({ type: 'bigint', name: 'id_cidade' })
idCidade: string
#Column('text', { name: 'nome' })
nome: string
// Entities from these relations are displayed in the Schemas of Swagger UI
#OneToMany(() => Grupos, (grupos) => grupos.idCidade)
grupos: Grupos[]
#OneToMany(() => Instituicoes, (instituicoes) => instituicoes.idCidade)
instituicoes: Instituicoes[]
#OneToMany(() => Usuarios, (usuarios) => usuarios.idCidade)
usuarios: Usuarios[]
}
The entities from those relations are also displayed on my Schemas.
I want to only display Cidades, the entity imported by my module. I tried to use #ApiHideProperty() decorator to hide the relations but didn't work. Is the any workaround for this behaviour?
EDIT:
I found a stop-gap solution. My CRUD methods were returning the entity, for example, createCidade(): Promise<Cidade> {}
I implemented a ResponseDto (based on JSend standards). One of it's properties holds data like the created resource Cidade.
Instead of returning an entity my methods return this DTO. This removed all unwanted entities from Swagger UI's Schemas and replaced them with ResponseDTO.
I found a better solution. You can use the #ApiHideProperty() decorator on all relations of your TypeORM entity, that way it won't be loaded into Swagger-UI schemas.
Example: stopping Swagger from loading Password relation when I'm working with a method that return Users entity.
#Entity('users', { schema: 'public' })
export class Users {
...
#ApiHideProperty()
#OneToOne(() => Passwords, (passwords) => passwords.idUser)
passwords: Passwords
}
I have those sample entities with a N:N relation on TypeOrm:
export default class Model extends BaseEntity {
#ManyToMany(type => Market, market => market.id,{ onDelete: 'CASCADE'})
#JoinTable({ 'name': 'model_enabled_markets' })
marketsEnabled: Market[];
//...
}
export default class Market extends BaseEntity {
#ManyToMany<Model>(type => Model, model => model.id,{ onDelete: 'RESTRICT'})
enabledModels: Promise<Model[]>;
//...
}
When about to save a new Model instance to the database, if I have the ids I need to place on the marketsEnabled, is there any way I can use them directly? Or do I need to query the required Markets with those IDs, and assign an array with them?
TypeORM expects that all entity objects (will) exist in a relation array (this is necessary, for example, because of the cascade option). Besides that, typescript also expects an object that matches that of the model, so it is probably not enough to just pass an object with an id field only.
To manipulate the join table directly, it is best to create it yourself as an entity class. This allows you to add or remove individual foreign id rows without first loading all relation entries in the navigation properties (relation arrays) of linked entity objects.
In Angular 2, a child component can get its parent component injected through a constructor parameter. Example:
#Component({...})
export class ParentComponent {
...
}
#Component({...})
export class ChildComponent {
constructor(private parent: ParentComponent) { }
...
}
This works nice and well as long the parent and child are of different types.
However, another typical use case is a tree structure where each tree node is displayed as a separate component. What should we do if each of the tree node components should have access to its parent? I have tried this:
#Component({...})
export class TreeNodeComponent {
constructor(private parent: TreeNodeComponent) { }
...
}
But this fails with the following runtime exception:
EXCEPTION: Cannot instantiate cyclic dependency!
I guess the reason is that Angular 2 injects the component itself instead of its parent component.
How can I tell angular to inject a component's parent component even though they are of the same type?
Plunker https://plnkr.co/edit/ddvupV?p=preview
This way it's working
constructor(#SkipSelf() #Host() #Optional() parent: TreeNodeComponent) {}
Plunker
#SkipSelf() is to not get oneself injected which would apply if TreeNodeComponent is requested
#Host() don't look further up than the host element
#Optional() ?? there is no parent TreeNodeComponent for the root node
See also http://blog.thoughtram.io/angular/2015/08/20/host-and-visibility-in-angular-2-dependency-injection.html
Angular2 looks into the current injector for a provider. In your case, TreeNodeComponent corresponds to the component itself.
The parent component instance is located into the parent injector.
I think that you could try to inject an Injector class to have access to the parent injector and then get the instance of the parent component. Something like that:
#Component({
(...)
})
export class TreeNodeComponent {
constructor(injector:Injector) {
let parentInjector = injector.parent;
let parent = patentInjector.get(TreeNodeComponent);
}
}
See this link for the documentation of the Injector class:
https://angular.io/docs/ts/latest/api/core/Injector-class.html
That said, I think that the Gunter's comment about binding and shared service is particularly relevant...
This post has been solved thanks to Günther. However, I would like to follow up based on the architectural feedback I got.
First and foremost: I completely agree that the TreeNodeComponent use case example is an anti pattern. A data driven component like a tree this should be controlled by data binding. My apologies for this anti pattern.
However, my actual use case (which is more complex to explain) is that I want to develop an advanced dropdown menu. Requirements:
The dropdown should have arbitrary number of levels (menu, submenu, subsubmenu etc)
The dropdown is defined at design time - its content is not based on dynamic data.
It should be possible to attach event handlers (_)= to each dropdown item.
It should be possible to insert custom control components into the dropdown.
A usage example:
<dropdown label="Actions">
<dropdown-item label="Action 1" (click)="action1()"></dropdown-item>
<dropdown-item label="Action 2" (click)="action2()"></dropdown-item>
<dropdown-item label="Submenu">
<dropdown-item label="Action 3.1" (click)="action31()"></dropdown-item>
<dropdown-item label="Action 3.2">
<dropdown-slider (change)="changeHandler()"></dropdown-slider>
</dropdown-item>
<dropdown-item label="Submenu">
<dropdown-item label="Action 3.3.1" (click)="action331()"></dropdown-item>
<dropdown-item label="Action 3.3.2" (click)="action332()"></dropdown-item>
</dropdown-item>
</dropdown-item>
</dropdown>
My consideration is that this would be hard to implement using data binding. It's much practical to be able to bind event handlers and include custom components this way.
But I might be wrong! Any opinions about this are highly welcome!
I am trying to set up a hasMany relationship for my Style model (hasMany('color_style')), and from what I understand of the documentation, it looks for a style attribute on ColorStyle instances, but my api is sending the attribute style_id, not style. How do I tell the ColorStyle model to read the style_id attribute from the api into the style attribute of the local model (and to translate it back when sending requests)?
The JSON from the api:
{
id:1,
color_id:1,
style_id:1,
customer_id:1,
active_flag:null,
created_at:"2015-02-13T22:35:23.857Z",
updated_at:"2015-02-13T22:35:23.857Z"
}
The Ember Model:
App.ColorStyle = DS.Model.extend({
color: DS.belongsTo('color'), // should be tied to color_id from api
style: DS.belongsTo('style'), // should be tied to style_id from api
customer: DS.belongsTo('customer'), // should be tied to customer_id from api
active_flag: DS.attr('boolean'),
created_at: DS.attr('date'),
updated_at: DS.attr('date')
});
You can add a custom serializer, but your code will be much cleaner, if you avoid this:
http://emberjs.com/api/data/classes/DS.RESTSerializer.html
http://emberjs.com/api/data/classes/DS.RESTSerializer.html#method_extractSingle
My problem should be obvious, but I just don't see the light right now :-(
I have two domainclasses like this:
class Parent {
String name
static hasMany = [children: Child]
}
class Child {
String name
}
Now I should be able to find the Parent of a child by using the dynamic finder of the Parent like:
Parent.findByChildren([someChild] as Set)
But I get a hibernate error stating that I've got a grammar error in my hibernate SQL:
Caused by: java.sql.SQLException: No value specified for parameter 1
And for the reference: someChild IS a concrete instance. And I would like to avoid Child to have an explicit parent in the definition.
How then can I go from the Child to the Parent?
Best Regards,
Christian Sonne Jensen
Just to end this question, I wanted to report a solution to my "problem". I'm using a namedQuery in the Parent entity (Customer or Producer) like this:
Class Customer {
static hasMany = [channels: Channel]
static namedQueries = {
findByChannel {
channelId ->
channels {
eq 'id', channelId
}
}
}
}
Then I find the Customer like this:
def customers = Customer.findByChannel(channel.id).list()
In this way the Channel are relieved of the burden of knowing anything about who references it, and I don't have to do any artificial relationship tables.
I still think that it must be some kind of mistake that I cannot use one of the dynamic finders:
Customer.findByChannels([channel] as Set)
Maybe the dynamic finders doesn't take one-to-many relationsships into account, and only works for simple attributes??? (I'm using Grails 1.3.1)
Thanks for your replies though!
Christian Sonne Jensen
If you don't want the parent foreign key on the child, you'll have to create a join table for the parent that serves as a surrogate for the child:
class ParentalRelationship {
static belongsTo = [parent: Parent, child: Child]
}
You could then have helper methods on the parent to query for children through the ParentalRelationship object.
With your real implementation of Customers, Channels, and Producers, chances are that you'd want a many-to-many relationship anyways as a channel wouldn't belong to a single customer (or a single producer).
Maybe a better way is to write in the chield the belongsTo something like this:
static belongsTo = [parent: Parent]
And then you can use:
Chield c = ...
Parent parent = c.parent
I would invert it:
class Parent {
String name
static Set<Child> getChildren() {
Child.findAllByParent(this) as Set
}
}
class Child {
String name
Parent parent
}
This uses the same database structure (the child table has a foreign key to parent) but makes it easy to go from one side to the other without being explicitly bidirectional.
One thing does change. Instead of this:
def parent = ...
parent.addToChildren(new Child(...))
parent.save()
you do this:
def parent = ...
def child = new Child(parent: parent, ...).save()
This is more performant because you don't need to load the entire collection just to persist a new child.