Declaring model metadata

Rum translates model classes into a list of rum.fields.Field instances using the rum.interfaces.IRepositoryFactory which knows how to introspect each kind of model objects.

This list of fields can be queried by the view layer to render an appropiate widget to allow viewing or creating each field as well as validating that the data the user submits is valid.

It is this abstraction the one that allows different kind of models to share the same view and viceversa since it de-couples both implementations.

Customizing fields

Rum may not always guess right what kind of data a particular field is supposed to store since it is not possible to derive their semantic meaning without resorting to extremely fragile heuristics (like treating a field named “email” as an email address). For example, a text field might as well hold an email address or a url or a password...

We have several ways to override the list of fields Rum will see for each model.

Using a class decorator

Probably the most straight-forward way is to decorate the model class with the rum.fields.FieldFactory.fields() class decorator. However, this has the disadvantage of coupling Rum to our domain model which could make reusing the domain model a bit harder since we can no longer package it without depending on Rum.

Lets see an example, we’ll customize the fields of the Movie model we just wrote in the Rumifying your models - A tutorial

from rum import fields

class Movie(Model):
    # code omitted...
    fields.FieldFactory.fields(
        'title',
        'genre',
        'filmed_on',
        'director',
        'actors',
        fields.HTMLText('synopsis')
        )
    # code omitted...

Declaring fields without modifying the domain model

However, the preferred option is to assign this metadata sepaerate from the package where the domain model lives, in the tutorial we would have done it in the app.py module.

from rum import fields
from model import Movie

fields.FieldFactory.fields(Movie, (
    'title',
    'genre',
    'filmed_on',
    'director',
    'actors',
    fields.HTMLText('synopsis')
    ))

Notice that we’re no longer modifying the code inside model.py and the similar, but slightly different, syntax of the same rum.fields.FieldFactory.fields() method

Note

There’s another way to customize the way Rum interprets models but it will not be documented yet. It involves extending generic functions and is very powerful but the API is still in a state of flux.

What effect does this have?

By providing a list of field names and a rum.fields.HTMLText instance named synopsis we’ve told Rum that from this model it should only care about these particular fields in the user interface (our users don’t care about the meaningless id primary key since it is an implementation detail). Field names as strings tell rum that we want it to guess what kind of fields are those but only those and in that particular order. A rum.fields.Field instance tells Rum that it should not guess what kind of field synopsis is since we’re explictly telling it that it is a field that will hold HTML text.

Note

The view layer is not obliged to do something with this extra information, (although it should probably do). They are just hints that it can interpret to render a specific widget if it knows how to do it.

A complete list of available fields is at the rum.fields document. The list is far from complete, if you miss any kind of field please drop by the rum-discuss mailing list and tell us.