aontu

Back to the Rails application overview

Generate Rails code with aontu templates

Follow a component tree, template markers, emit rules, and replacements from the model to Rails source files.

Rendered from test/system/rb-solar/doc/rails-code.md in the engine repository. The model, the generators, the committed application and the check.sh that renders and validates all of it are in test/system/rb-solar/.

The Rails example uses seven Ruby templates and one aontu document to write the application files marked as generated. A template specifies both the output paths and the rules that fill them. Read the model guide first for setup and the entity properties.

Separate instructions from output

Open the routes generator. Lines beginning with #- contain aontu instructions. Other lines provide Ruby output:

#- @"../model.aon"
#-
#- out: file("config/routes.rb", [
#-   [
# Generated by aontu from model.aon. Do not edit.

The import loads model.aon relative to the generator file. file names one output file, config/routes.rb relative to the output directory, and its second argument is the list of lines that fill it. A bare string among them is one line of target text.

Ruby treats every #- line as a comment. This lets the template remain parseable Ruby, with placeholders where generated values will go. Check its syntax:

ruby -c gen/routes.rb

A syntax check does not run the template as a Rails application. aontu must first evaluate the marked instructions and substitute model values.

What the tree is

file(name, children) builds one node of a component tree: the shape a generator runtime writes to disk. folder, line and content are its neighbours; every prop each one takes is checked at the call, so a misspelled one is refused rather than dropped.

Each file supplies a name and its lines. The generator writes the target’s text explicitly; aontu knows no languages, and nothing here makes it invent a Rails implementation.

The generator’s import and its own declarations form one document. The imported file supplies service and entity; the generator adds out, computed from those values. You evaluate the generator, not model.aon on its own.

See file in the function index for the full list and what each one takes.

Follow one value into a route

The root-route rule selects the service’s root value:

#-   emit([$.service.root], {
#-     match: string
#-     replace: ROOT: _
#-     body: [
  root "ROOT"
#-     ]
#-   })

emit visits the selected values and uses the first matching rule. Here the selection is a one-item list containing "planets#index". match: string admits that value, _ refers to it, and replace substitutes it for ROOT in the output line.

Inspect the tree without writing anything:

aontu template gen/routes.rb > work/routes.aon
aontu model get out work/routes.aon

One of its lines is:

  root "planets#index"

The other rules iterate over entities to write browser routes, API routes, and action routes. Replacement names must not overlap: aontu refuses a table with both COLLECTION and COLLECTION_HELPER.

Produce one file per entity

The Active Record generator builds its files with emit($.entity, ...). For each matching entity it computes the name from .id, such as app/models/moon.rb.

Inside that file, a second rule emits the class body. .class is the current entity’s class name. A nested selection of required fields writes presence validations:

#-         emit(filter(.field, { required:true }), {
#-           match: name: string
#-           replace: FIELD: .name
#-           body: [
  validates :FIELD, presence: true
#-           ]
#-         })

filter selects fields with required: true; the rule reads each selected field’s name. For Moon, this produces validations for diameter, id, kind, name, and planet_id.

Write the model files into the Rails application directory:

aontu render gen/model.rb app
aontu render --check gen/model.rb app

The first command writes the files this generator names. The second builds them again and compares their bytes with the files on disk. It does not check files owned by other generators.

Choose the generator for the output

GeneratorReadsWrites under app/
routes.rbService root, entity paths, and actionsconfig/routes.rb
migrate.rbOrdered entities, fields, and indexesdb/migrate/*_create_*.rb
seeds.rbOrdered entities and prepared seed rowsdb/seeds.rb
model.rbEntity classes, associations, and required fieldsapp/models/*.rb
api_base.rbError definitionsapp/controllers/api/base_controller.rb
api_controller.rbEntity fields, paths, parents, and actionsapp/controllers/api/*_controller.rb
ui_controller.rbEntities and their parentsapp/controllers/*_controller.rb
views.aonFields, labels, and route helpersapp/views/*/*.html.erb

The view generator uses ordinary aontu syntax with ERB lines in backtick strings. The template marker mechanism does not support ERB’s delimited comment syntax, so this generator is an aontu file rather than an ERB template.

Understand the checks’ limits

aontu never parses the target: every line a generator writes is text whose syntax it has not validated. Ruby syntax checks and Rails behaviour tests provide the evidence about that text.

Writing the tree leaves files outside it alone. When a rule is removed or a generated path changes, review and remove the obsolete file yourself. The change-and-check guide shows the complete regeneration loop and a field change to try.