Creating a Blog

This article wants to give you a basic idea of how to create a blog in a Rails app based on Scrivito. It guides you through building a little test app, a site containing a simple blog and some blog articles on it. We won't go into too much detail but, if required, point you to other, more elaborative articles instead.

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

You might want to make yourself familiar with the Scrivito SDK Basics first if you are new to Scrivito.

It makes no difference whether the website you are creating with Scrivito represents a blog in itself or should only contain one. The underlying principles are the same.

To summarize the key aspects of a blog as it will be outlined here: we require models and views for individual blog posts as well as a blog overview page. The latter should offer pagination. We would also like to support commenting and will implement this using a third-party service, disqus.

Individual blog posts

There should be an easy way to create blog posts, and they should automatically appear on the blog once published. Therefore, we'll create a BlogPostPage model and later use search functionality to find all instances of this model.

We'd like the blog posts to be taggable. Also, each of them should be provided with an abstract which can be displayed on an overview page. So, we require corresponding attributes, tags and abstract.

Let's go ahead and generate the BlogPostPage model. Note that you can omit the “Page” suffix because the page generator automatically appends it if it's missing:

Copy
$ rails g scrivito:page BlogPostPage
      create  app/models/blog_post_page.rb
      create  app/controllers/blog_post_page_controller.rb
      create  app/views/blog_post_page/index.html.erb
      create  app/views/blog_post_page/details.html.erb
      create  app/views/blog_post_page/thumbnail.html.erb

Now, extend the new model so that it includes the required attributes:

Copy
# app/models/blog_post_page.rb

class BlogPostPage < Obj  
  attribute :title, :string
  attribute :body, :widgetlist
    
  # Additional attributes
  attribute :tags, :stringlist
  attribute :abstract, :html
  attribute :created, :date
  attribute :author, :string
  
  default_for :created do
    Time.zone.now
  end
end

Note that you can also specify model attributes in the generator call by appending them as arguments, e.g. title:string, to it.

As you can see, we've added two other attributes that could be useful for sorting the blog posts later on: created and author. The actual content of a blogpost will be stored in its body attribute. The created attribute is automatically set to the current date using the defaults API.

Next, let's provide the blog post view:

Copy
# app/views/blog_post_page/index.html.erb

<%= scrivito_tag(:h1, @obj, :title) %>
<%= scrivito_tag(:div, @obj, :created) %>
<%= scrivito_tag(:div, @obj, :author) %>
<%= scrivito_tag(:div, @obj, :abstract) %>
<%= scrivito_tag(:div, @obj, :body) %>

For now, the view simply consists of helper calls for rendering the attributes of a blogpost.

Blog overview page

When creating a blog, you will need an entry or overview page, on which, for example, abstracts of the first ten or so posts could be displayed. We'll name the model of the overview page BlogOverviewPage. You can generate the model in exactly the same manner as before:

Copy
$ rails g scrivito:page BlogOverviewPage
      create  app/models/blog_overview_page.rb
      create  app/controllers/blog_overview_page_controller.rb
      create  app/views/blog_overview_page/index.html.erb
      create  app/views/blog_overview_page/details.html.erb
      create  app/views/blog_overview_page/thumbnail.html.erb

We require some kind of pagination on this overview page. If you have done the Pagination tutorial, you are already familiar with the concept. So, let's use this for our overview page. First, create the view:

Copy
<!-- app/views/blog_overview_page/index.html.erb -->

<h3>Blog</h3>

<% @blog_posts.each do |blog_post| %>
  <h4><%= link_to(scrivito_value(blog_post.title), scrivito_path(blog_post)) %></h4>
  <p><%= scrivito_tag(:div, blog_post, :abstract) %></p>
<% end %>

<%= link_to("previous page", @previous_page) if @previous_page %>
<%= link_to("next page", @next_page) if @next_page %>

Then provide the controller:

Copy
# app/controllers/blog_overview_page_controller.rb

class BlogOverviewPageController < CmsController
  POSTS_PER_PAGE = 10

  def index
    offset = params[:offset].to_i

    blog_posts_query = BlogPostPage.all.order(created: :desc)
    blog_posts_query.batch_size(POSTS_PER_PAGE).offset(offset)
    @blog_posts = blog_posts_query.take(POSTS_PER_PAGE)    

    total = blog_posts_query.size

    if offset > 0
      @previous_page = scrivito_path(@obj, offset: offset - POSTS_PER_PAGE)
    end

    if total > offset + POSTS_PER_PAGE
      @next_page = scrivito_path(@obj, offset: offset + POSTS_PER_PAGE)
    end
  end
end

POSTS_PER_PAGE lets you adjust the number blog posts per page to your needs.

We still need an instance of the blog overview page. Open the rails console and run the following commands:

Copy
irb(main):026:0> Scrivito::Workspace.current = Scrivito::Workspace.create(title: "Blog")
=> <Scrivito::Workspace id="637a5605b7e60e3a" title="Blog">
irb(main):027:0> BlogOverviewPage.create(_permalink: "blog")
=> <BlogOverviewPage id="0dfe05b066fd7131" path="">

Now that there's an instance of the blog, we'd like it to be easily accessible. That's why we created a Permalink named “blog.”

If you switch to the working copy you just created, you can navigate to http://127.0.0.1:3000/scrivito/blog where you should see the overview page. However, it's empty except for the “Blog” title. Just create a couple of blogposts using the “Create page” item from the page menu, then revisit your blog overview. You should see something like this:

Comments section

This example utilizes disqus to support discussions on blog posts. If you already have a disqus account or don't mind creating one on disqus.com, choose  “Add Disqus To Site” from the top right menu. Memorize the shortname, and then create the comments view:

Copy
<!-- app/views/blog_post_page/_comments.html.erb -->

<div id="disqus_thread"></div>
<script>
  var disqus_shortname = "EXAMPLE"; // replace EXAMPLE with your disqus shortname
  var disqus_identifier = "#{post.id}";

  (function() {
    var dsq = document.createElement("script");

    dsq.type = "text/javascript";
    dsq.async = true;
    dsq.src = "//" + disqus_shortname + ".disqus.com/embed.js";

    (document.head || document.body).appendChild(dsq);
  })();
</script>

Now, all that's missing is to render the comments into the blog posts by appending the following line to the blog post view:

Copy
<!-- app/views/blog_post_page/index.html.erb -->

<%= render("blog_post_page/comments", post: @obj) %>

Using tags

Tags are convenient for categorizing blogposts by the topics they cover. Offering the tags as filters makes it easy for visitors to choose a topic they are interested in.

To achieve this, we're going to render a small tag cloud on the overview page. If one of the tags is clicked, we want it to be passed to the controller. We'll do this via the “tag” parameter. This way, we can filter the BlogPostPage instances by the given tag.

We already have the tags attribute to work with in our BlogPostPage model definition. In this attribute the tags of each blog post are stored. So, in our BlogOverviewPageController, if a tag was passed to it, we can search for posts whose tags attribute contains this tag. Go ahead and change the controller to:

Copy
# app/controllers/blog_overview_page_controller.rb

class BlogOverviewPageController < CmsController  
  POSTS_PER_PAGE = 10

  def index
    offset = params[:offset].to_i

    blog_posts_query = BlogPostPage.all.order(date: :desc)
    # If a tag is provided, then filter by it:    
    blog_posts_query.and(:tags, :equals, params[:tag]) if params[:tag].present?    
    @blog_posts = blog_posts_query.take(POSTS_PER_PAGE) 

  end
end

It would be convenient to have a method in our model that finds a decent amount of tags for use in the tag cloud view. So, let's define one on the BlogPostPage class and call it all_tags. We'll add it to the blog overview page:

Copy
# app/models/blog_post_page.rb

class BlogPostPage

  def self.all_tags
    all.batch_size(0).facet("tags", limit: 50)
  end
end 

Now that everything has been prepared, go ahead and create the tag cloud view. It iterates over the tags returned by the BlogPostPage.all_tags method and creates a link for each of them, pointing to the filtered search. Note that the facet method used in the helper already gives us the name as well as the count of a tag. Take a look at the SDK documentation on faceting for further information.

Copy
<!-- app/views/blog_overview_page/_tag_cloud.html.erb -->

<h3 class="h4">Tags</h3>

<hr/>

<% BlogPostPage.all_tags.each do |tag| %>
  <%= link_to(scrivito_path(@obj, tag: tag.name)) do %>
    <%= tag.name %> (<%= tag.count %>)
  <% end %>
<% end %>

Next, we add the tag cloud to our overview page. Of course you could also add it to every blog post. We are working with bootstrap classes, so in case you aren't using it, you might want to modify the view or add your own CSS rules.

Copy
<!-- app/views/blog_overview_page/index.html.erb -->

<h3>Blog</h3>

<div class="col-md-9">
  <% @blog_posts.each do |blog_post| %>
    <h4><%= link_to(scrivito_value(blog_post.title), scrivito_path(blog_post)) %></h4>
    <p><%= scrivito_tag(:div, blog_post, :abstract) %></p>
  <% end %>
</div>

<div class="col-md-3">
  <%= render("blog_overview_page/tag_cloud") %>
</div>

<%= link_to("previous page", @previous_page) if @previous_page %>
<%= link_to("next page", @next_page) if @next_page %>

At this point, you can change the tags of a page only on the console. So, finally, we want to enable editors to easily add and remove them. Just add a tag editor to the details view of the BlogPostPage:

Copy
<!-- app/views/blog_post_page/details.html.erb -->

<%= scrivito_details_for("Tags") do %>
  <%= scrivito_tag(:div, @obj, :tags) %>
<% end %>

Editors can now select a BlogPostPage in the content browser and then edit its tags in the sidebar. If you add a few tags to your blog posts, you should see them on the overview page.

That's it! You've created a blog that supports commenting and utilizes tags! Happy blogging!