Using Link Lists and References

Link lists and references are an important concept in Scrivito. Technically, there are link, linklist, reference, and referencelist attribute types next to other attribute types such as string, html, date, etc. You can add as many of these attributes as needed to any object class so that the instances of such an object class, the CMS objects, are equipped with these link lists or references, respectively.

Learn more about the CMS data structures and their building blocks: object classes and attributes.

Links and link lists

A link list may contain any number of links. As with links contained in the body or in an html attribute of a CMS object, these links may point to CMS objects or external content. However, they are not rendered automatically when the page or page component represented by the CMS object is rendered. Link lists serve a special purpose, their semantics is given to them by an application-specific use case. Thus, code must be written to make a link list work as it is supposed to.

Link lists are link containers. They are suitable for implementing use cases in which a page or page component needs to handle external resources, or present any number of links to the visitor. If, for example, an article page is to render a list of links pointing to other topically related articles, this list is best represented as a linklist attribute. This is a flexible solution for maintaining external links or a combination of external and internal links.

Assuming that there is a dedicated ArticlePage object class containing a related_topics link list attribute, its view could render the links it contains as follows:

<ul>
  <% @obj.related_topics.each do |link| %>
    <li>
      <%= link_to(link.display_title, scrivito_path(link)) %>
    </li>
  <% end %>
</ul>

Every link in a linklist attribute is represented as a Link object with several methods, e.g. title, url, or destination_object, supporting even sophisticated use cases around linking. For details, please refer to the corresponding API documentation.

References and reference lists

As opposed to links, references are meant to merely point to other CMS objects, without carrying the semantics of links with them. While the contents of a reference attribute is a single CMS object, a referencelist attribute contains an array of any number of target objects. This is handy for providing access to all kinds of internal resources relevant to the CMS object being rendered.

For rendering an avatar, for example, its location can be defined by means of a reference attribute, e.g. author_avatar_image, pointing to the image:

<%= scrivito_image_tag @obj, :author_avatar_image %>

Instead of a reference type attribute, you can also use a link or linklist attribute.

Manipulating links and references with Ruby

When changing a link or linklist attribute of an existing CMS object, this object needs to be updated to persist the new attribute value. In fact, this holds true for all changes to any type of attribute. When creating a CMS object, the attribute values passed to it are stored automatically, of course. Examples:

Copy
# Update the URL of a link
link = obj.my_link
link.url = "http://www.example.com"
obj.update(my_link: link)

# Update the 'current_campaign' link of an object
obj.update(current_campaign: Scrivito::Link.new(obj: Obj.find('55dd1ce50ecc41c8')))

# A link list can be defined as an array of links
Obj.create(link_list: [
  Scrivito::Link.new(url: "http://www.example.com", title: "External link"),
  Scrivito::Link.new(obj: other_obj, title: "Internal link")
])

# A reference attribute can be set by passing a CMS object to it
Obj.create(reference: other_obj)

# To set a reference list, pass an array of CMS objects as the value
Obj.create(reference_list: [object, other_obj])

As can be seen above, a link list is represented as an array of links, a reference list as an arrays of CMS objects.

For the purpose of generating sorted navigation lists, the pages subordinate to a page (the child pages) can be sorted using a custom referencelist attribute named child_order (see Making Navigations Sortable for details):

Copy
# Reference lists: sort children by their title
child_order = obj.children.sort_by &:title
obj.update(child_order: child_order)

Since every link list is an array of links, you can extend them, manipulate their items individually, sort them, etc. Don't forget to update the CMS object containing the link list afterwards:

Copy
# Append the homepage to a linklist
link_list = obj.link_list
link_list << Scrivito::Link.new(obj: Obj.root, title: 'Return to homepage')
obj.update(link_list: link_list)

# Change the third element of a linklist to an internal link
link_list = obj.link_list
link_list[2].url = nil
link_list[2].obj = other_obj
obj.update(link_list: link_list)

# Sort a linklist by link display titles, and remove external links
link_list = obj.link_list
link_list.sort_by! &:display_title
link_list.reject! &:external?
obj.update(link_list: link_list)