The content-type system in LocomotiveCMS allows you to define and use various types of relations between models.
Let's go through classical Author <-> Book example to learn each relation type provided by LocomotiveCMS. First we're going to have the very basic models of Authors and Books containing only **name** fields:
## Belongs To: the Book belongs to the Author
With this type of relation we can store a link to an Author along with the Book, which immediately becomes callable as a property of the book instance:
"Belongs To" is the easiest relation to set up. You just need to add the following to **app/content_types/books.yml**:
The key `
author` here is a property that we will call on a book instance. It does not have to match the name of related model. For example, we could name our relation `
class_name` parameter (vice versa) must contain the slug of the model; otherwise, we couldn't know which model exactly we want to bind here.
Also, we may want to add the `
required: true` option if the book without an author shouldn't exist in our library.
You could also have used the Wagon relationship generator:
bundle exec wagon generate relationship books belongs_to authors`
This also generates the has_many relationship as explained in the next chapter.
Ok. Once we're done, we may want to add some records to see how it works. Let's add the following to the **data/authors.yml**:
Internally, and for SEO purposes, Locomotive will convert these keys in computer readable slugs.
Leo Tolstoy will become leo-tolstoy and Anton Tchekhov will become anton-tchekhov
Then add these records to the **data/books.yml**:
Defining a relationship between content type entries in YAML data files
Have you noticed? The relationship between the records in **data/authors.yml** and **data/books.yml** is made through the subkey "author" of the books.
And beware: the value of such subkey needs to be defined by using the slugs automatically created by Locomotive.
If you use natural human readable language, the relationship will not work. So be careful here.
Now if we add the following snippet to the index page...
...we'll see the list of the books with their authors:
As you may notice it's perfectly legal to create an arbitrary amount of Books pointing to one Author. And this brings us to the next type of relation.
## Has Many: the Author has many Books
It is quite unusual for the Author to have only one Book published. That's why we need another type of relation to describe how Books are connected to the Author.
We did most of the work for establishing `
has_many` relation in the last section. From the point of view of the root object this type of relation is no more than an inverted belongs_to. This structure is quite obvious: book `
belongs` to author and author has many books belonging to the author. That's it! We've come full circle.
Let's add a `
books` property to **app/content_type/authors.yml**:
Some new parameters are introduced here. The parameter inverse_of specifies which property of the foreign model is used to establish the belongs_to relation with the current model. Its name is self-explanatory: ``
what property of the RELATED model would be an inversion of the property that we're going to define on THIS model?`
Or what property of the related model could tell us if we're connected?
It makes perfect sense if you just imagine the Tolstoy record asking Anna Karenina: "Is that me who has created you?"
The last parameter ui_enabled allows you to select whether the related item should be editable right from the editing screen of the current model in the admin panel. If you turn on this option you'll be able to conveniently edit or create related items during editing or creation of the root item.
Let's take a look at how it works. To do so, we'll take the first author which happens to be Tolstoy and ask him which books he wrote:
The output would be the following, as expected:
## Many to Many: the case of the Book written in collaboration
Let's imagine that Tolstoy and Tchekhov wrote a book in co-authorship which in fact never happened even though they lived in the same time. But for learning purpose it would be fun to think that their partnership brought a brilliant book called "Anna Karenina in the Cherry Orchard" to the world.
It breaks our perfect world in no time. Now one Author can have many Books, and one Book can be written by a group of Authors. This type of relation is called Many-to-Many and it is considered the most complex relation.
Let's make some changes in **app/content_type/books.yml**
That's it. Now we can attach as many Books to each Author as we want, and vice versa.
The only thing left is to take a look at the seed data for this kind of relation (**data/books.yml**):
Use the slugs!
Have you noticed? In the array making the references to the authors collection, we use the slugs of the authors.
Now if we take the last book and iterate over authors, we will see `
Leo Tolstoy and Anton Tchekhov`:
## Tags: special relation
Locomotive has embedded support for tags. To use them, you just have to add a field of type tags to your model. Then you'll be able to scope by tags, like this:
A common mistake with relations involves mistreatment of the property. Just remember, that for any relation except the `
belongs_to` you have a collection even though it consists of only one element.