-
Notifications
You must be signed in to change notification settings - Fork 3
2.2 Using Sourcery with models
Sourcery is a code generator for Swift, built on top of Apple's own SourceKit. It’s an open-source project created by Krzysztof Zabłocki
Sourcery allows you to generate boilerplate code automatically. It parses your code and gives you detailed information about it (variables, methods, their types, names, etc.), that can be used to generate boilerplate code and to get rid of repetitive tasks.
Sourcery works with stencil templates. (also with swift and javascript)
Because Vapor models have a lot of convenient protocols that they can conform, there’re a lot of same code, that could be generated for us automatically.
AutoModelGeneratable.stencil
template has been created for that purpose.
Open terminal and run this command to install Sourcery using Mint.
Download Mint Package manager
brew tap yonaskolb/Mint https://github.com/yonaskolb/Mint.git
brew install mint
Download latest Sourcery package with Mint
mint install krzysztofzablocki/Sourcery
Sourcery uses annotations for passing arguments in template. This makes using sourcery really flexible.
In order to tell sourcery that we want to generate code for our Vapor model, add this annotations above class definition:
// sourcery: AutoModelGeneratable
// sourcery: toJSON, fromJSON, Updateable, Preparation
class SomeClass: Model {
}
AutoModelGeneratable
annotation is required and will generate code for Keys
structure, static var entity
property(for DB table name) and RowRepresentable
protocol.
toJSON
, fromJSON
, Updateable
, Preparation
, ResponseRepresentable
, Timestampable
are optional and will generate appropriate protocols for each annotation.
If model has relations, we can explicitly add annotation to emphasise relation details or it will be done implicitly, for relation properties annotations are optional:
Example 1: property connected to User model, and is also unique
// sourcery: relatedModel = User, unique = true
var userId: Identifier
Example 2: property connected to City model(if not added explicitly in annotation, it will be taken from property name), not unique and also can be NULL as it's optional
var cityId: Identifier?
Handling nested JSON Fields
Model JSON representation can have nested JSON fields for its relations.
For this purpose we have nestedJSONField
and nestedJSONRepresentableField
annotations.
-
nestedJSONField
for primitive types(String, [String], Int and so on...) -
nestedJSONRepresentableField
for types that conform JSONRepresentable protocol([SomeModel], SomeModel so on...)
Template will use place
as field name. If function is called registrationForm
, field name will be snakecased automatically("registration_form"
):
// sourcery: nestedJSONRepresentableField
func place() throws -> Place? {
return try parent(id: placeId).get()
}
Or field like this("speakers_photos": ["test", "test", "test"])
// sourcery: nestedJSONField
func speakersPhotos() throws -> [String] {
return ["test", "test", "test"]
}
Ignoring fields in JSON
Sometimes we don't need some properties to be generated in makeJSON() implementation. For example if we use "place" from example above property "place_id" make no sense there, so we ignore it.
// sourcery: ignoreInJSON
var placeId: Identifier
Auto enum generation support
Also if model has enums they can also be generated. For example, enum variable with two cases: video and slide, would be annotated like this:
// sourcery: enum, video, slide
var type: ContentType
Time to generate code
After this, run SourceryGenerator.command
script that will generate code in new file and will place it in model's folder.(Model must have necessary variables and initializer for them)
If you use Xcode, do not forget to add generated file to project and choose App
as target membership for it.