Best practices – rails
Overview
Rails Builder and the Content Delivery service are very flexible. This makes them quite powerful, but it also means that it is easy to use them in sub-optimal ways.
For example, there is nothing to stop you creating a single, giant template in Rails Builder and then, in your client app, making a single call to get all the content provided via the template as a single, huge response object. But it is not the best way to do things.
This page aims to provide some best practices that will help you to manage the trade-off between UI smoothness and response object size.
Suggested best practices
Different clients (for example, mobile apps and smart TV apps) may have different screen layouts, different behaviour, and different business logic.
For example, a smart TV app may use its screen space to show multiple categories on a single screen, whereas a mobile app might split the same content up into several different screens. In this case, it would be better to create separate mobile and smart TV layouts in Rails Builder than to use a single layout for both.
Layouts determine that content that devices receive from Content Delivery. Templates are containers that contain one or more layouts.
Typically, you would:
Create a template for each screen in your application.
Make sure that each template targets all destinations (device types).
For each template, leave the default layout that is automatically created to also target all devices.
If required, create additional, device-specific layouts.
This ensures that a request from a client app to Content Delivery will always return something, as there will always be a currently-applicable layout that applies to every device type.
Rails Builder allows you to specify the device(s) that each layout applies to (TV, desktop, tablet, or mobile).
See the Layout Destination Selection field in Creating, editing and deleting layouts.
The Content Delivery service supports paged content – that is, delivering only part of the required data at a time. It supports horizontal paging; that is, within a rail, you can retrieve just enough items to fill the visible space, rather than all the items in the rail.
See:
Refer to Retrieve all or part of the rails and related content for a template to get all the rails in a template.
Then refer to Retrieve a specific rail and its contents to get the specific rails you want, with their contents. Use the
limit
,offset
, andpage
parameters to get only the number of content items that you need.
It is a good idea to retrieve more content than you need to display initially. That way, when the user scrolls, the newly-displayed part of the screen is already populated and they do not need to wait for items to load.
A good starting point is to retrieve twice as many items as the screen can display, in each direction, which means:
Get twice as many rails as the screen can display vertically.
Within each rail, get twice as many items as the screen can display horizontally.
You can use the multiplier that works best for you to manage the trade-off between UI performance and response object size.
Different devices will typically have different scrolling speeds. For example, a user on a mobile device can scroll faster than a one using a TV remote to scroll.
So you may find that a different multiplier is appropriate for each type of device.
See the links in Use the paging functionality, above.
Example
If you have decided that you want to get twice as much content than can be displayed, both vertically and horizontally, then you would need to do something like this for the template that corresponds to the screen you are displaying:
Make a GET request to Content Delivery's
templatesummary
endpoint to get all the rails for the template's current layout:CODEhttps://server:port/contentdelivery/v1/templatesummary/{templateid/templatename}
Let's say there is space in the viewport for five rails (vertically). So you want to get ten rails. For each of the first ten rails listed in the response from the above call, you would make a GET request to Content Delivery's
rails
endpoint:CODEhttps://server:port/contentdelivery/v1/templateviews/{templateid/templatename}/rails/{railId}?limit=10&page=1
Use the
limit
andpage
parameters to get the required number of horizontal items in each rail:limit
– the number of items per pagepage
– the page for which to return items (starts at 1)
When the user scrolls a rail horizontally, make additional GET calls to the
rails
endpoint to retrieve more items:CODEhttps://server:port/contentdelivery/v1/templateviews/{templateid/templatename}/rails/{railId}?limit=10&page=2
CODEhttps://server:port/contentdelivery/v1/templateviews/{templateid/templatename}/rails/{railId}?limit=10&page=3
... and so on.
When the user scrolls vertically, repeat step 2 to retrieve more rails.
Typically different teams will be responsible for template creation and client app integration. It is important for both teams to:
Understand these best practices.
Know what each other are doing.
This approach allows the client integrators to know which template they should be using for each screen. It is up to you how you manage this, but suggested options include:
Using an agreed naming convention for templates, layout, and rails.
Using remote configuration to enable the client app to know which templates to use.
Remote configuration is outside the scope of the Content Delivery service. However, it does have an endpoint that allows the client to retrieve all the available templates.
You have to name your templates, layouts, and rails. Deciding on a sensible naming convention for each will help avoid confusion.
You are recommended to name the first template default
or home
.
The recommended way to make changes to the content of a particular screen is to:
Create a specific template for that screen.
Create a default layout, so that the template always contains content.
Create different layouts for the template. These layouts can then be scheduled in Rails Builder.
This is easier to manage than switching templates on the client side.
Layouts are not pushed to client apps, nor is there a notification mechanism.
Changes to layouts and layout scheduling are only picked up when the client app requests rails from Content Delivery.
See Scheduling layouts.
It may be that you will need to make changes to template metadata that break backwards-compatibility (for example, changing the key name for a key/value pair that is already in use).
In this case, creating a new version of an existing template is encouraged.
Once all clients have been upgraded to the new version, you can retire the older template.
This approach incurs an overhead – any changes (e.g., scheduling new versions) must be made to all such templates.
Whenever you edit a layout and save it, a new version is created. If necessary, you can roll back to a previous version. Rolling back creates a new version in the history that is the same as the version you are rolling back to.
Use versioning to roll back to an earlier version if you have made changes to the layout that you no longer require.
Do not use versioning where scheduling would be more appropriate – that is, when you want to make changes to a layout that only apply for a specific time period.
When a client app makes a request for rails to Content Delivery, it returns the rails from the latest version of the applicable layout (that is, the one that is applicable for the device type and for the time the request is made (if you are using scheduled layouts)).
Custom metadata (key/value pairs) can be added at three levels:
To templates
To rails
To sections within rails
To individual content items
Which level you add them at depends on what you are trying to achieve.
For example, you could:
Add a key/value pair to a rail to indicate to the client app that it should style that rail differently from other rails.
(Similarly, you could do the same for sections or individual content items to present them differently within their rail.)Add key/value pairs to a custom section that the client app could use to insert an item to represent a third-party application.
You might have separate key/value pairs to specify:The title of the app
The app's bundle ID
The URI of the image to be used for the app within the rail
Note: Only use this approach in situations where images are not available from OpenTV Video Platform.For regular content items, you are recommended to get images from the ImageService.
See:
You can use scheduling to create a layout that only applies for a specific time period (for example, for Christmas or other important seasonal event).
This allows you to make planned changes in advance without having to edit the current (live) layout.
Never make changes to a current (live) layout. Always use scheduling instead.
See Scheduling layouts.
Templates can be arranged in a hierarchy of parent, child, and sibling templates.
Arrange your templates in the same hierarchy as the screens in your application. For example, if your app has a Home screen that allows users to access a Sports screen and a Kids screen, make your Sport and Kids templates children of your Home template.
Alternatively, your application can dynamically generate its screen hierarchy based on the template hierarchy.
When your application calls Content Delivery to get the templates, the template objects in the response are organised in the hierarchy in the same way as they are organised in Rails Builder.
See:
Adding too many rails to a page or adding too much content to an individual rail can lead to a situation where users will give up on scrolling and not reach content that you would like them to see.
Recommendations:
If you want to add many rails, put them on separate pages/templates instead of all on one page/template.
Use the looping scroll interface paradigm (where the UI starts at the first rail again when the user reaches the bottom and starts from the beginning of the rail if the user reaches the end of the rail).
It is possible to add individual items to a rail. But it is not very flexible.
Adding items to a content group allows you to reuse the group of items in multiple rails.
You can:
Create a dynamic content group, which contains content that match the specified criteria (in OpCon).
Create a content group that contains the content that you specify (through API calls).