Skip to content

Commit

Permalink
feat: add individual methods to serialize attributes, relations and c…
Browse files Browse the repository at this point in the history
…ompute properties
  • Loading branch information
thetutlage committed Jan 17, 2020
1 parent 71ee4c8 commit a1382e8
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 33 deletions.
7 changes: 7 additions & 0 deletions adonis-typings/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,13 @@ declare module '@ioc:Adonis/Lucid/Model' {
save (): Promise<void>
delete (): Promise<void>
serialize (): ModelObject
serializeAttributes (raw?: boolean): ModelObject
serializeComputed (): ModelObject

serializeRelations (raw: true): { [key: string]: ModelContract | ModelContract[] }
serializeRelations (raw: false | undefined): ModelObject
serializeRelations (raw?: boolean): ModelObject | { [key: string]: ModelContract | ModelContract[] }

toJSON (): ModelObject
refresh (): Promise<void>
preload: ModelBuilderPreloadFn<this>
Expand Down
2 changes: 1 addition & 1 deletion adonis-typings/relations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ declare module '@ioc:Adonis/Lucid/Relations' {
> {
readonly type: TypedRelations['type']
readonly relationName: string
readonly serializeAs: string
readonly serializeAs: string | null
readonly booted: boolean
readonly model: Model
relatedModel (): RelatedModel
Expand Down
83 changes: 56 additions & 27 deletions src/Orm/BaseModel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1260,54 +1260,83 @@ export class BaseModel implements ModelContract {
}

/**
* Converting model to it's JSON representation
* Serializes model attributes to a plain object
*/
public serialize () {
public serializeAttributes (raw: boolean = false): ModelObject {
const Model = this.constructor as ModelConstructorContract
const results = {}

/**
* Serializing attributes
*/
Object.keys(this.$attributes).forEach((key) => {
return Object.keys(this.$attributes).reduce<ModelObject>((result, key) => {
const column = Model.$getColumn(key)!
if (!column.serializeAs) {
return
return result
}

const value = this[key]
results[column.serializeAs] = typeof (column.serialize) === 'function'
result[column.serializeAs] = typeof (column.serialize) === 'function' && !raw
? column.serialize(value, key, this)
: value

return result
}, {})
}

/**
* Serializes model compute properties to an object.
*/
public serializeComputed (): ModelObject {
const Model = this.constructor as ModelConstructorContract
const result: ModelObject = {}

Model.$computedDefinitions.forEach((value, key) => {
const computedValue = this[key]
if (computedValue !== undefined && value.serializeAs) {
result[value.serializeAs] = computedValue
}
})

/**
* Serializing relationships
*/
Object.keys(this.$preloaded).forEach((key) => {
return result
}

/**
* Serializes relationships to a plain object. When `raw=true`, it will
* recurisvely serialize the relationships as well.
*/
public serializeRelations (raw: true): { [key: string]: ModelContract | ModelContract[] }
public serializeRelations (raw: false | undefined): ModelObject
public serializeRelations (
raw: boolean = false,
): ModelObject | { [key: string]: ModelContract | ModelContract[] } {
const Model = this.constructor as ModelConstructorContract

return Object.keys(this.$preloaded).reduce((result, key) => {
const relation = Model.$getRelation(key as any)! as RelationshipsContract
if (!relation.serializeAs) {
return
return result
}

const value = this.$preloaded[key]
results[relation.serializeAs] = Array.isArray(value)
if (raw) {
result[relation.serializeAs] = value
return result
}

result[relation.serializeAs] = Array.isArray(value)
? value.map((one) => one.toJSON())
: value.toJSON()
})

/**
* Serializing computed properties as last. This gives the option to re-write
* keys which are defined as attributes or relations.
*/
Model.$computedDefinitions.forEach((value, key) => {
const computedValue = this[key]
if (computedValue !== undefined && value.serializeAs) {
results[value.serializeAs] = computedValue
}
})
return result
}, {})
}

return results
/**
* Converting model to it's JSON representation
*/
public serialize () {
return {
...this.serializeAttributes(),
...this.serializeRelations(false),
...this.serializeComputed(),
}
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/Orm/Relations/BelongsTo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ ModelConstructorContract
public type = 'belongsTo' as const
public booted: boolean = false
public relatedModel = this.options.relatedModel
public serializeAs = this.options.serializeAs || this.relationName
public serializeAs = this.options.serializeAs === undefined
? this.relationName
: this.options.serializeAs

/**
* Available after boot is invoked
Expand Down
4 changes: 3 additions & 1 deletion src/Orm/Relations/HasMany/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ ModelConstructorContract
public type = 'hasMany' as const
public booted: boolean = false
public relatedModel = this.options.relatedModel
public serializeAs = this.options.serializeAs || this.relationName
public serializeAs = this.options.serializeAs === undefined
? this.relationName
: this.options.serializeAs

/**
* Available after boot is invoked
Expand Down
4 changes: 3 additions & 1 deletion src/Orm/Relations/HasManyThrough/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ ModelConstructorContract
> {
public type = 'hasManyThrough' as const
public booted: boolean = false
public serializeAs = this.options.serializeAs || this.relationName
public serializeAs = this.options.serializeAs === undefined
? this.relationName
: this.options.serializeAs

public relatedModel = this.options.relatedModel
public throughModel = this.options.throughModel
Expand Down
4 changes: 3 additions & 1 deletion src/Orm/Relations/HasOne/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ ModelConstructorContract
public type = 'hasOne' as const
public booted: boolean = false
public relatedModel = this.options.relatedModel
public serializeAs = this.options.serializeAs || this.relationName
public serializeAs = this.options.serializeAs === undefined
? this.relationName
: this.options.serializeAs

/**
* Available after boot is invoked
Expand Down
4 changes: 3 additions & 1 deletion src/Orm/Relations/ManyToMany/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ ModelConstructorContract
public type = 'manyToMany' as const
public booted: boolean = false
public relatedModel = this.options.relatedModel
public serializeAs = this.options.serializeAs || this.relationName
public serializeAs = this.options.serializeAs === undefined
? this.relationName
: this.options.serializeAs

/**
* Available after boot is invoked
Expand Down
Loading

0 comments on commit a1382e8

Please sign in to comment.