Creating a Small News Site

If you would like to develop a Scrivito-based web application then this article is for you. It guides you through building a little test app, a site consisting of a simple homepage and a list of news on it.

This guide is based on our instructions for integrating Scrivito. You can complete it in no time after creating your Scrivito account. Integrating Bootstrap is optional, but recommended for this tutorial.

Overview

We're assuming that you are fine with the homepage in general but would like to be able to add news articles that should appear on a sidebar. Also, the news items should be limited to the latest five of them, sorted by date in reverse order. And because of the limited amount of space on the sidebar, only the abstract of each of them should be shown. The title and a more link of every item should point to the corresponding news page where the full text of this particular article is displayed, together with its date, information about the author, you name it.

To display a single news article, we are going to create a NewsArticlePageController that has its own view that renders all the article details. The controller will be chosen automatically by the Rails router if the Scrivito model is of the NewsArticlePage class. This class will be defined to hold values of particular attributes, e.g. the title, the date of the news, an abstract to be shown on the homepage, the full text to be shown on the details page, and the author's name.

For the list of news on the homepage, we will use the built-in search engine to query NewsArticlePage models, sorted and limited the way we want.

And we need a way to actually create news articles and and fill them with content.

Generate the news article page

Let's start with the page showing a single news article. We are going to create the Ruby classes for the NewsArticlePage model and the NewsArticlePageController controller. Also, we need to define the type of data such a model needs to hold, i.e. the attributes. Then, a view is required that renders the attributes with an appealing design.

For all of this, the Scrivito SDK comes with a page generator that creates the model and the controller for the page, plus the index view as well as the page properties and thumbnail views for in-place editing:

Copy
$ rails g scrivito:page NewsArticlePage
      create  app/models/news_article_page.rb
      create  app/controllers/news_article_page_controller.rb
      create  app/views/news_article_page/index.html.erb
      create  app/views/news_article_page/details.html.erb
      create  app/views/news_article_page/thumbnail.html.erb

Let's walk through all that generated code. Don't be intimidated, it is not as much as it seems.

Modify the generated object class model

The generator called above created a new object model class, NewsArticlePage, with a set of basic attributes. Open the model file in your text editor and add the attributes we want to be associated with news articles:

Copy
# app/models/news_article_page.rb

class NewsArticlePage < Obj
  attribute :title, :string
  attribute :created, :date
  attribute :author, :string
  attribute :abstract, :html
  attribute :news, :widgetlist
end

You can now create instances of NewsArticlePage, store data in their attributes, and retrieve them later on.

Model and controller

Let's verify that the model works. Open the Rails console to create a working copy (or use an existing one) and make it the current working copy. All Scrivito commands run in the context of a working copy. If none is specified, Scrivito implicitly selects the working copy that represents the published content (which cannot be modified directly).

$ rails c

> Scrivito::Workspace.create(title: 'News')
=> <Scrivito::Workspace id="3e3ba209b4e92b34" title="News"> > Scrivito::Workspace.current = Scrivito::Workspace.find_by_title("News") => <Scrivito::Workspace id="3e3ba209b4e92b34" title="News"> > NewsArticlePage.all.to_a => []

No errors, that's good. There aren't any news articles yet because we haven't created any, but that's fine at the moment. Let's continue with the NewsArticlePageController, which is responsible for displaying an individual page for a news article. The generator has already created the controller for you, too:

Copy
$ cat app/controllers/news_article_page_controller.rb
class NewsArticlePageController < CmsController
end

The CmsController is the base class of all Scrivito pages, i.e. pages that render a Scrivito model such as our NewsArticlePage model. Even the routing has already been taken care of. The Scrivito routing matches URLs whose path includes an object ID or a so-called permalink, loads the requested object, determines its object class, then derives a corresponding controller name, and finally dispatches the request to the index action of this controller:

$ bundle exec rake routes
[…]
     cms_id                  (/)(*slug-):id(.:format) 
     scrivito_permalink      /*permalink 

If, for example, there is a news article whose ID is 123, requesting localhost:3000/123 causes the routing to match 123 as the object ID. Then, it  would fetch this object from the Scrivito database and determine its object class, NewsArticlePage. After deriving the controller name, NewsArticlePageController, by applying the naming convention, the routing finally dispatches the request to NewsArticlePageController#index to have the page rendered.

There are two things still missing yet. First, an actual news article, and, second, a view containing HTML code to be rendered. We're going to change the generated view first by editing 

app/views/news_article_page/index.html.erb.

Copy
<%= scrivito_tag(:h1, @obj, :title) %>
<%= scrivito_tag(:div, @obj, :created, class: "date") %>
<%= scrivito_tag(:div, @obj, :author, class: "author") %>
<%= scrivito_tag(:div, @obj, :abstract) %>
<%= scrivito_tag(:div, @obj, :news) %>

This view contains a couple of calls to the scrivito_tag helper, which is defined in the Scrivito SDK. This helper generates a tag as specified by the first argument, takes the current object (always stored in the @obj variable, in our view this is the NewsArticlePage model instance), and renders its title etc. attributes, one after the other.

Create a news article on the console for testing

To test this page, we require at least one NewsArticlePage model. For now, create one on the Rails console. Again, first switch to your working copy because you cannot create anything in the published content.

Copy
$ rails c
> Scrivito::Workspace.current = Scrivito::Workspace.find_by_title("News")
=> <Scrivito::Workspace id="3e3ba209b4e92b34" title="News">

> NewsArticlePage.create(title: "Test News", created: Date.today, author: "Me", abstract: "On this wonderful day, wonderful things happened")
=> <NewsArticle id="3f5c02e0d774a7f7" path="">

The above output of the last command in the Rails console includes an object ID, 3f5c02e0d774a7f7. This is a unique identifier that was randomly generated by Scrivito and never changes during the lifetime of this particular object. When you go through this tutorial, you will certainly get a different object ID.

You can now test the news article page in the browser. Visit localhost:3000, open the Scrivito sidebar on the right hand side, and you'll see the list of working copies that exist next to the published content.

Select the working copy you used for creating the news article, e.g. “News.” For the website, this has the same effect as switching the working copy in the Rails console as we did above.

Taking another look at Scrivito's sidebar, you will notice that the menu lists more options this time. This is because working copies can be renamed, deleted, collaborated on, etc. All those options are not available for the published content, which is why they did not appear previously.

Select Changes, and in the dialog that's opened, select the NewsArticlePage we created before in the Rails console. You should see something like this:

Edit the news article

As mentioned before, the view contains several calls to the scrivito_tag helper to render the individual attributes of the news article. This helper is also responsible for the in-place editors associated with the attributes. For example, the title can be edited by means of a single-line edit field, the abstract with an HTML5 WYSIWYG editor, and the widgets contained in the news widget attribute can be edited using their individual menu accessible through the green widget handle. The menu includes items for inserting the news text, a new image, etc. Images can be uploaded by means of drag 'n' drop. All these editing facilities are already baked in.

When developing locally, you are authorized as a system user by default (unless you already added log-in functionality to your application), so go ahead. On the editing panel, click the Edit button. This activates widget handles and in-place editors on your page whereever a scrivito_tag helper is called in the view.

Click one of the attributes to edit it. Changes made to the attributes are automatically saved in the background. Click outside the attribute on the page background to close the current editor. Feel free to play around a bit.

Create a news article directly on the website

In a previous section, we created a news article by using a Ruby command in the Rails console. This is obviously not the way Scrivito users should create news articles. So, the next step is to create news articles directly on the website.

For a start, it's sufficient to duplicate existing pages. Using the page menu in the top right corner of the Scrivito control panel, you can duplicate the page you are currently viewing.

After clicking Duplicate page, a copy of the news article is made, and you are redirected to it. You can now edit the copy. Go ahead and change the title, date, and abstract.

When you select Show changes from the working copy menu, you will notice that the list of article pages has become longer. Create one or two more news articles by duplicating an existing one so that the news article list we'll render on the sidebar of the homepage later on gets populated.

Integrate the list of latest news

Our next goal is to have up to five news articles displayed in reverse order on the sidebar. To achieve this, open the index view of the news article in your text editor, and append this code:

Copy
<%= content_for :sidebar do -%>
  <h3>News</h3>
  <% NewsArticlePage.latest_news.each do |news| -%>
    <h4><%= link_to scrivito_value(news.title), scrivito_path(news) %></h4>
    <p><%= scrivito_tag(:div, news, :abstract) %></p>
  <% end -%>
<% end -%>

This view iterates over NewsArticlePage.latest_news and renders each item. The titles are then linked to the full articles.

NewsArticlePage.latest_news doesn't exist yet. Open app/models/news_article_page.rb in your text editor again, and add this method:

class NewsArticlePage < Obj
  attribute :title, :string
attribute :date, :date
attribute :author, :string
attribute :abstract, :html
attribute :news, :widgetlist
  def self.latest_news     all.order(date: :desc)   end end

The new latest_news class method utilizes the integrated search engine to determine all NewsArticlePage instances and orders them reversely by their date.

Next we need to add the sidebar into our application view at app/views/layouts/application.html.erb.

Copy
<div class="container-fluid">
  <div class="row">
    <div class="col-md-8"> 
      <%= yield %>
    </div>
    <div class="col-md-4">
      <%= yield :sidebar %>
    </div>
  </div>
</div>

Reload the page and you should see the sidebar next to the article.

Publish the working copy

As announced above, we are going to publish our work. Until then, it's only a working copy not visible to the public and can even be discarded. Being able to discard a working copy comes in handy if, for example, you've written a script that didn't work as it should.

Select Publish from the Scrivito sidebar.

Congratulations! You laid the foundation of a news website with Scrivito. :)