Creating and Modifying Object Classes

With Scrivito, CMS objects and widgets are the basic entities representing and containing the CMS content. While CMS objects typically represent web pages or generic data such as images, widgets are pre-built page components made available to editors for populating pages with many and varied kinds of content. Please refer to CMS Objects, Widgets, and Classes for further details on how these entities work in Scrivito.

Defining models

CMS objects and widgets are based on corresponding Ruby classes, their models. In order to read from and write to the CMS using the Scrivito SDK, you need to define these models first.

Normally, your application already has at least two models, an “Obj” object model defined in app/models/obj.rb and a “Widget” model defined in app/models/widget.rb.

These two models are generated by the “install” generator of the Scrivito gem. To provide custom object and widget models, subclass the “Obj” and “Widget” classes. You can use the supplied “page” and “widget” Rails generators to have Scrivito generate your custom Ruby classes for you.

In order to generate an object model named “ProductPage,” run:

rails generate scrivito:page product_page

This generates the corresponding Ruby class, “ProductPage,” in app/models/product_page.rb:

Copy
class ProductPage < Obj 
  attribute :title, :string
  attribute :body, :widgetlist
  attribute :child_order, :referencelist
end

The “page” generator additionally creates the required views as well as the controller.

Analogously, to generate the “ProductWidget” widget model, run (the generator appends the “widget” part if it's missing):

rails generate scrivito:widget product

Again, this generates the corresponding “ProductWidget” Ruby class in app/models/product_widget.rb:

Copy
class ProductWidget < Widget
end

The “widget” generator also creates the required views but no controller because widgets cannot be accessed individually.

Now you have two model classes: a “ProductPage” CMS object model and a “ProductWidget” widget model.

For the purpose of preventing object and widget classes from appearing in the page and widget type browsers used by editors, the hide_from_editor class method is available. This method only affects in-place editing, not the API.

Copy
class ProductPage < Obj
  # Suppress in page selection dialog
  hide_from_editor

  attribute :title, :string
  attribute :body, :widgetlist
  attribute :child_order, :referencelist
end

Defining attributes

To individualize your models, you can now define their attributes. For this, Scrivito provides the attribute method which accepts three arguments: the name of the attribute, its type, and, optionally, the selectable values of enum and multienum type attributes. For details about the attribute method, please refer to the Scrivito::AttributeContent.attribute API documentation.

If you wanted your “ProductPage” CMS object model to be equipped with a “summary” attribute of the string type, you would complement your model like this:

Copy
class ProductPage < Obj
  # New attribute
  attribute :summary, :string

  attribute :title, :string
  attribute :body, :widgetlist
  attribute :child_order, :referencelist
end

Note that for Scrivito to treat CMS objects as binary objects (e.g. images), they need to have a binary attribute named “blob” which can be defined in a model using attribute :blob, :binary.

Now, define the string attributes named “title” and an enum attribute named “category” in the “ProductWidget” model:

Copy
class ProductWidget < Widget
  attribute :title, :string, default: 'Untitled Product'
  attribute :category, :enum, values: ["toys", "food", "electronics"]
end

See Specifying Default Attribute Values for further options when adding attributes to an object class.

You can remove an attribute from a CMS object or a Widget class simply by removing the definition from your source code. However, this does not delete any actual data stored in the CMS, which may be fine or even intended in some cases. But if you plan to remove an attribute associated with lots of existing content, you should clear the data from the CMS by writing empty values into the attribute prior to removing its definition.

Using the model

You should be able to read from and to write to the Scrivito CMS. Open the Rails console and type:

Copy
workspace = Scrivito::Workspace.create(title: "Test working copy")
Scrivito::Workspace.current = workspace

Now, create an instance of the “ProductPage” model, fill it with data and store it:

Copy
page = ProductPage.create(title: "Products")
page.title  # => "Products"
page.body   # => []
page.id     # => "1234567812345678"

To find and update the stored page, use:

Copy
page = ProductPage.find("1234567812345678")
page.update(title: "Product Overview")
page.title # => "Product Overview"

You can also create some widgets and store them in the “body” attribute of product_page:

Copy
racing_car = ProductWidget.new(title: "Racing Car", category: "toys")
melon = ProductWidget.new(title: "Cantaloupe Melon", category: "food")

page.update(body: [racing_car, melon])
page.body.map { |widget| widget.title }
# => ["Racing Car", "Cantaloupe Melon"]

tv = ProductWidget(title: "Digital TV", category: "electronics")
iron = ProductWidget(title: "Iron", category: "electronics")
page.update(body: page.body + [tv, iron])
page.body.map { |widget| widget.title }
# => ["Racing Car", "Cantaloupe Melon", "Digital TV", "Iron"]