Modeling Object Associations

Active Record lets you define how models are connected with each other: Its associations (“belongs_to”, “has_many,” etc.) allow you to specify (and in some cases restrict) the relationship between your different sets of data, mainly for keeping this data consistent with respect to its structure and dependencies:

Copy
class Book < ActiveRecord::Base
  has_many :chapters
end

Please refer to the RailsGuides for further details. — Now, how are relationships modelled with Scrivito?

Incorporated content models

With Scrivito, most of your data represents content: pages, binaries, widgets – all of them may come in different flavors implemented as model classes, e.g. “NewsPages”, “BlogPostPages”, “ImageWidgets”, etc. Some instances of such model classes are connected with others by their nature: a widget belongs to a page, either directly or through another widget; a page can have any number of widgets if it has been equipped with one or more widgetlist attributes. In these cases, one model directly incorporates one or more other unique models.

Referenced content models

In addition to models incorporating others, content can be referenced, meaning, for example, that a widget displaying an image simply needs to point to the image object. For this, the widget class requires an attribute of the reference type:

Copy
class ImageWidget < Widget
  attribute :img_obj, :reference, only: Image
end

If there are several image widget classes, e.g. one for a stand-alone image and one for a gallery, instances of both may reference one and the same image object. Instead of a reference attribute, the gallery widget would use a referencelist attribute for pointing to any number of image objects. (There's more on attribute types in general as well as on how to use references)

Of course, reference and referencelist attributes are not limited to pointing to image objects. You can use them to create navigations (in which they point to page objects) or to associate pages or widgets with products, contact persons or other kinds of modular content.

Using the links_to and refers_to search operators, Scrivito lets you do reverse lookups to determine the CMS objects pointing to specific objects in a one-to-many or many-to-many fashion. There also is a wrapper method available, backlinks, that uses links_to for finding CMS objects linking to a particular object.

Association helpers

To make it easier to establish and use associations between CMS objects, Scrivito includes several helpers that follow the naming of Active Record Associations (but don't utilize Active Record).

For example, the commonly presented author/books relationship (one Book “belongs to” one Author, one Author “has many” Books) can be expressed with Scrivito like this:

Copy
class Book < Obj
  attribute :title, :string
  belongs_to :author
end

class Author < Obj
  attribute :first_name, :string
  attribute :last_name, :string
  has_many :books
end

hawking = Author.create(first_name: 'Stephen', last_name: 'Hawking')
history_of_time = Book.create(title: 'A Brief History of Time', author: hawking)
grand_design = Book.create(title: 'The Grand Design', author: hawking)

The “Book” and “Author” classes are interconnected via corresponding attributes that are subject to the specified association type, so you can access the attributes of an associated instance accordingly:

Copy
history_of_time.author
# => <Author id='xyz' first_name='Stephen' last_name='Hawking'>

history_of_time.author.first_name
# => 'Stephen'

hawking.books.to_a
# => [<Book id='abc' title='A Brief History of Time'>, <Book id='123' title='The Grand Design'>]

hawking.books.map(&:title)
# => ['A Brief History of Time', 'The Grand Design']

For further details, please refer to the Scrivito SDK documentation of belongs_to, belongs_to_many and has_many.

Restricting model use

As a default, Scrivito lets you create pages of any type anywhere on your website. Analogously, you can place any of the available widgets onto a page or into a container widget (such as a “2ColumnWidget”). If this isn't what you want (because you'd like your blog to consist of blogposts only), you can define individual rules on where to permit or deny the use of particular page or widget types.

You can also restrict the classes of the models reference or referencelist attributes may reference in order to limit, for example, a PDF widget to PDF files – which is absolutely recommendable. See the only parameter of reference attribute definitions for details.