-
Clone the repository.
- If you're part of the
NijiDigital
GitHub organization, you can directly clone the repo and you'll be able to push new branches to it - If you're not part of the
NijiDigital
GitHub organization, either ask us to be part of it (we're pretty open to adding new members, and that's our preferred way for you to contribute), or fork the repository in your own GitHub and clone your fork
- If you're part of the
-
Create a new branch, make your changes in the code or template
-
Try running your local, modified version of
gyro
withbundle exec gyro
(see below) -
Run the tests & check code style using
bundle exec rspec
&bundle exec rubocop
(see below) -
Don't forget to add an entry in the
CHANGELOG.md
to explain your new feature or fix and credit yourself -
Once everything is ok and the tests and rubocop all pass, push your changes
-
Open a Pull Request to merge your branch into
master
- Unless you used a fork, CircleCI will perform the tests on your PR, including running the unit tests and running
rubocop
- Unless you used a fork, CircleCI will perform the tests on your PR, including running the unit tests and running
- Open a terminal
cd
into the directory where you cloned the repo- Run
bundle install
if you haven't run it before- If you don't have
bundler
installed on your machine, you'll have to install it first usinggem install bundler
.
- If you don't have
- Use
bundle exec
to run the following commands — so that it uses the versions specified in theGemfile
, especially the local copy ofgyro
instead of the one installed globally on your system- Use
bundle exec rspec
to run the tests - Use
bundle exec rubocop
to check the code style of your ruby code - Use
bundle exec gyro …
to run the local version of gyro in this repo
- Use
$ bundle install # Install any necessary ruby dependencies
$ bundle exec rspec # Run the tests
$ bundle exec rubocop # Check for code style
$ bundle exec gyro -v # Run gyro -v using the local code, not the system-installed gyro
$ bundle exec gyro -l # Same for any gyro command you want to test
In ruby, unit tests are called "specs".
gyro
uses rspec
to run the tests and test its ruby "specs".
Those unit tests (specs) are located in the spec
subdirectory, containing:
spec/fixtures/xcdatamodel
: the input xcdatamodel used as input test fixtures of the various the testsspec/fixtures/<lang>
: the output fixtures (the output expected for each test) for various templates (currently:java
,kotlin
,swift
)spec/gyro
: the tests themselves
The tests in spec/gyro
consist of invoking gyro
with various input xcdatamodel
, templates and options, letting gyro generate the output in a temporary folder, then compare the generated output with the expected one found in spec/fixtures/<lang>
.
This means that the specs for gyro
are only based on textual comparison, checking that it generates the expected… text. They don't check if what is generated will actually compile in Swift/Java/Kotlin (that would require to embed a swift, java & kotlin compiler just for that…)
So when you update the Unit Tests, be sure to test the code you make gyro
generate (the one located in spec/fixtures/<lang>
) with an actual compiler to be sure that it will actually compile.
Gyro is composed of two parts:
- Parsers, which takes an input model and outputs an intermediate representation of that model
- Today
gyro
has only one parser, to parsexcdatamodel
files. Maybe we'll add more parsers to support more input formats in the future
- Today
- Generators, whose role are to transform the intermediate representation (see model classes in
lib/gyro/parser/xcdatamodel/*.rb
) into some output (either JSON or using a template engine)- Today
gyro
only has two generators, one to use Liquid templates to generate its output, and one to generate JSON output.
- Today
This allows us to be flexible about input and outputs we support.
- Source code for Parsers are located in
lib/gyro/parser
- Source code for Generators are located in
lib/gyro/generator
- The Liquid generator uses templates to define what code to generate. Gyro comes with bundled templates which can be found in
lib/templates/*
gyro
uses Liquid 3.0, because Liquid 4.0 requires ruby 2.1 which was not installed by default until macOS High Sierra (previous versions of macOS had ruby 2.0 installed by default) — and we didn't want to impose that requirement of ruby 2.1 to use gyro
.
Once macOS High Sierra will be widespread enough, we'll probably migrate to Liquid 4.0, making
gyro
require ruby 2.1, but as of today that's not the case yet.
However, we extended Liquid 3.0 inside gyro to patch it and add some filters (see below)
Our whitespace patch to Liquid 3.0 (see lib/gyro/generator/liquid/whitespace_patch.rb
) allows to support {%-
and -%}
in addition of {%
and %}
(like Liquid 4 does).
Using those allows to remove whitespaces before/after the tag on the generated text. This allows to have more readable templates conserving some indentation in the template for things like {%- if … -%}
and {%- for … -%}
tags without adding extra whitespaces in the generated code
gyro
also add some filters to Liquid (see lib/gyro/generator/liquid/filters.rb
) that you can then use inside your *.liquid
templates. This includes filters like:
escape_quotes
to turn"
into\"
snake_to_camel_case
to turnhello_world
intoHelloWorld
snake_case
to turnHelloWorld
intohello_world
uncapitalize
to turnHelloWorld
intohelloWorld
titleize
to turnhelloWorld
intoHelloWorld
delete_objc_prefix
to remove uppercase prefixes and turnABCFidelityCard
intoFidelityCard
If you plan to write your own templates:
- It's generally easier to duplicate an existing template and adapt it than starting from scratch
- You can find the documentation for the Liquid templating language here and elsewhere on the net
- Each template is represented by a folder which must at least contain:
- Ideally, a
README.md
file documenting the template - an
entity.liquid
file representing the template to use for each entity - an
entity_filename.liquid
file which must only contain one line, representing the template to use to generate the file name for each given entity - an
enum.liquid
file representing the template to use for each enum used in the model, if the entities of your model contains enum attributes - an
enum_filename.liquid
file which must only contain one line, representing the template to use to generate the file name for each enum
- Ideally, a
Liquid is a well known templating language, so chances are your favorite text editor (Sublime Text, Atom, …) has a syntax highlighting plugin for Liquid files. Be sure to check and install it, that will make editing your .liquid
files way more readable!
Liquid is more commonly used to generate HTML output rather than Swift/Java/Kotlin/… so some of those syntax highlighting plugins might be named "HTML+Liquid" or "HTML Liquid", but that is still better than monochrome text 😉
If you find yourself going back and forth between your text editor to modify a template and your terminal to run bundle exec gyro
to test your template and see what is genenerated, there are some solutions to improve that.
One of them is kicker, which allows you to "watch" a directory for changes (typically the directory of the template you're editing) and automatically execute an arbitrary command (typically bundle exec gyro -t … -o … -m …
) when one of the file is changed.
kicker -e "bundle exec gyro -t your_template_being_edited -o /tmp/gyro_test -m spec/fixtures/xcdatamodel/some_model.xcdatamodel" lib/templates/your_template_being_edited
That way, you can easily open side-by-side in your favorite editor both your template and the output generated in some temp folder, and let kicker
run in the background to auto-update the output without having to switch back to the Terminal each time 👍
Kicker is not the only solution allowing to do that (just one of them), some editors might even have a similar feature embedded directly