By default, AdonisJS will serialize model property names to snake_case
. Meaning, if we send our model using JSON, or manually serialize the model, the property rememberMeToken
would be converted to remember_me_token
.
const user = await User.findOrFail(1) const rememberMeToken = user.rememberMeToken // 👈 camelCase here post.serialize() // 👈 then after serializing /* { id: 1, remember_me_token: null // 👈 it'll change to snake_case } */
Copied!
If we didn’t want this to happen, and instead have our property remain camelCased
as rememberMeToken
when serialized, we could manually add the serializeAs
property on our model’s properties, but that can be time-consuming.
So, in this lesson, we’ll be taking a look at how to quickly and easily do this throughout all models using Naming Strategies.
Get An AdonisJS Project
If you’d like to follow along and need a project you can go ahead and clone down the repository from our AdonisJS Bouncer series. This project has auth, a couple of basic models, and CRUD for those models setup.
I’ll be cloning the project down as adonisjs-serializations
.
git clone <https://github.com/jagr-co/adonisjs-bouncer.git> adonisjs-serializations
Copied!
Install it’s dependencies, setup your environment variables by copying what is in .env.example
and open it up in your text editor of choice and you’re ready to go!
Adding A Camel Case Strategy
Within your project, go ahead and create a new folder under app
called Strategies
, you can place this elsewhere if you’d like. Then, within your Strategies
folder, create a new file called CamelCaseNamingStrategy.ts
.
Within this file, we’ll want a default exported class that extends AdonisJS’ default SnakeCaseNamingStrategy
, this is the strategy all models use by default.
import { SnakeCaseNamingStrategy } from '@ioc:Adonis/Lucid/Orm' export default class CamelCaseNamingStrategy extends SnakeCaseNamingStrategy { }
Copied!
- app
- Strategies
- CamelCaseNamingStrategy.ts
Next, we’ll want to define how our strategy should serialize our model property names. For this, we can define a method called serializedName
within our CamelCaseNamingStrategy
.
import { SnakeCaseNamingStrategy, BaseModel } from '@ioc:Adonis/Lucid/Orm' import { string } from '@ioc:Adonis/Core/Helpers' export default class CamelCaseNamingStrategy extends SnakeCaseNamingStrategy { public serializedName(_model: typeof BaseModel, propertyName: string) { return string.camelCase(propertyName) } }
Copied!
- app
- Strategies
- CamelCaseNamingStrategy.ts
Here we’ve defined a public method called serializedName
that accepts our model, of type BaseModel
, and the property name it’s currently trying to serialize. The model argument name starts with an underscore because we won’t be using it. Then, inside the method all we need to do is mutate our property name however we wish and return the mutated name.
So, in our example, we’re using AdonisJS’ cameCase
string helper to convert our property’s name to camel case.
There’s also a ton of other methods we can define using Naming Strategies to alter the default naming conventions for our models. For the full list, check out the Naming Strategy page of the documentation.
Applying Our Camel Case Strategy
Now that we have our strategy created, now we need to inform our model(s) to use it. We can do this by providing a new instance of our strategy’s class to the static namingStrategy
property within our model’s class.
// ... imports import CamelCaseNamingStrategy from 'App/Strategies/CamelCaseNamingStrategy' // 👈 our strategy export default class User extends BaseModel { // 👇 define a new instance of our strategy on the model public static namingStrategy = new CamelCaseNamingStrategy() @column({ isPrimary: true }) public id: number @column() public roleId: number @column() public username: string @column() public email: string @column({ serializeAs: null }) public password: string @column() public rememberMeToken?: string @column.dateTime({ autoCreate: true }) public createdAt: DateTime @column.dateTime({ autoCreate: true, autoUpdate: true }) public updatedAt: DateTime // ... other properties }
Copied!
- app
- Models
- User.ts
With this, when we serialize our User model all the camel cased properties will now remain camelCase
instead of the default snake_case
.
const user = await User.findOrFail(1) const rememberMeToken = user.rememberMeToken // 👈 camelCase here post.serialize() // 👈 then after serializing /* { id: 1, rememberMeToken: null // 👈 it'l now remain camelCase } */
Copied!
Applying Naming Strategy To All Models
So, we now know how to do this on a per-model basis. We could go through and add this to each model, but what would be better is to have our own BaseModel
that all our application’s models extend. This will allow us to define the naming strategy once. Plus, if we find ourselves in a similar situation in the future, all the prep work will be done and we’ll have a single spot, our BaseModel
, that we need to alter.
Creating Our Base Model
To prevent naming conflicts, for our app’s BaseModel
let’s use the name AppBaseModel
or something of the sort. This will prevent issues with auto-import and the like pulling in the wrong import location.
So, let’s create a new file within our Models directory called AppBaseModel.ts
. Then, inside this file, we’ll want a default exported class named AppBaseModel
that extends AdonisJS’ BaseModel
.
import { BaseModel } from '@ioc:Adonis/Lucid/Orm' export default class AppBaseModel extends BaseModel { }
Copied!
- app
- Models
- AppBaseModel.ts
Then, we can apply our CamelCaseNamingStrategy
directly to our AppBaseModel
.
import { BaseModel } from '@ioc:Adonis/Lucid/Orm' import CamelCaseNamingStrategy from 'App/Strategies/CamelCaseNamingStrategy' // 👈 import it export default class AppBaseModel extends BaseModel { public static namingStrategy = new CamelCaseNamingStrategy() // 👈 set as naming strategy }
Copied!
- app
- Models
- AppBaseModel.ts
Using Our Base Model
Next, we’ll want to go through all our application’s models and swap our AdonisJS’ BaseModel
with our AppBaseModel
, like the below.
// ... imports // 👇 remove AdonisJS' BaseModel import import { column, beforeSave, HasMany, hasMany } from '@ioc:Adonis/Lucid/Orm' // 👇 import our AppBaseModel instead import AppBaseModel from 'App/Models/AppBaseModel' export default class User extends AppBaseModel { // 👈 update to AppBaseModel @column({ isPrimary: true }) public id: number @column() public roleId: number @column() public username: string // ... other properties }
Copied!
- app
- Models
- User.ts
Here we’ve removed the import for AdonisJS’ BaseModel
from @ioc:Adonis/Lucid/Orm
. Then, we imported our new AppBaseModel
and swapped it out as the class our User models extends.
Do this for all models in your application, except your AppBaseModel
, and you’ll be all set with your new CamelCaseNamingStrategy
for all models. Plus, since you now have your own class all models extend, you have a singular place you can easily extend all your models for future changes.
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!