Blog / Development

Creating a Kentico Cloud Ruby on Rails Application


by Eric Dugre

Mar 6, 2019

The unofficial Kentico Cloud Ruby SDK is now available on GitHub. It’s still in beta, but contains most of the features you’ll need to retrieve published or draft content from Kentico Cloud to display in your Rails application. 

Follow this tutorial to get started on your cool Rails project!

Setting Up

To begin your project, you’ll need Ruby and Rails installed. You can install Ruby by choosing the appropriate method from their homepage. Then, install Rails using the guide. It should only take one command:

gem install rails


To create a new Rails project, I would recommend using the –O parameter which will create the project without a database. In this tutorial, we will not need a local database, and you may experience some difficulty installing the sqlite3 gem.

rails new kenticorails –O


Open your new Rails project in an IDE such as Visual Studio Code and open the Gemfile. Here, you add Ruby gems which your project requires to run. Add the delivery-sdk-ruby gem, and also the render_async gem (https://github.com/renderedtext/render_async).

gem 'delivery-sdk-ruby'
gem 'render_async'

Test Run

At this point your Rails application should at least run successfully. Run bundle install to install the gems in your Gemfile, then start the server. In VSCode, these commands can be run from a Bash terminal by pressing CTRL+`.

bundle install
rails server


Navigate to localhost:3000 in your browser, and you should see the default Rails welcome page:

ruby-welcome


Creating a Controller and View

Rails creates the default controller /app/controllers/application_controller.rb to use in your application. Let’s modify it so that we can use the KenticoCloud::Delivery::DeliveryClient in our controllers:

class ApplicationController < ActionController::Base
  PROJECT_ID = '<your-project-id>'.freeze  
  @@delivery_client = KenticoCloud::Delivery::DeliveryClient.new project_id: PROJECT_ID
end


Create home_controller.rb in the same directory which we will use to display some articles on our home page:

class HomeController < ApplicationController
  def index; end
end


For now, this controller has one action that will display index.html.erb; we’ll add the cool stuff in a bit! In the /app/views directory, create a new folder named “home” then the index.html.erb inside of it. You can add any HTML you want here, for now, I’ve added a placeholder for our article list:

<h1>Latest Dancing Goat Articles</h1>
<div>
 (coming soon)
</div>


Open the /app/config/routes.rb file and register our HomeController, then tell Rails we want to view HomeController’s index() action when accessing the main domain:

Rails.application.routes.draw do
  resources :home
  root 'home#index'
end


If you haven’t already, shut down the previous server by pressing CTRL+C in the terminal, then rerun the rails server to view your changes. There are no articles displaying yet, so let’s fix that.

Asynchronous Rendering

In this section, we’re going to add a new action to the HomeController that will asynchronously request articles from Kentico Cloud and display them on the home page. This is what the render_async gem is for: using this gem will allow your home page to load before Kentico Cloud even responds, and the content will be rendered once it’s received. Note that this is not necessary, but may speed up your site. Later in the “Resolving rich text” section, we’ll create a controller that doesn’t use render_async.

Let’s start with the required scripts for render_async to do its magic. Add the following to app/views/layouts/application.html.erb, just above the closing </body> tag:

<body>
 <%= yield %>
 <%= content_for :render_async %>
</body>


In app/views/home/index.html.erb, we need to tell render_async where to load our article list. Add the following block to the view where you want the articles to show:

<h1>Latest Dancing Goat Articles</h1>
<div>
 <%= render_async article_list_path %>
</div>


The render_async gem will request data from the article_list_path and load the response where the code block is placed. Let’s define the article listing path in app/config/routes.rb:

Rails.application.routes.draw do
  resources :home
  get :article_list, :controller => :home
  root 'home#index'
end


Create the article_list action in our HomeController, which will render a partial view when called:

class HomeController < ApplicationController
  def index; end
  def article_list
    render partial: "article_tile"
  end
end


Finally, create the partial view _article_tile.html.erb in app/views/home which will render when the article_list action is called. It can contain anything right now:

 <b>Articles are almost here..</b>


Run rails server and reload the home page. You’ll see that render_async has rendered _article_tile.html.erb view within the index view:


Now for the fun stuff!

Cloud-ifying Rails

It’s finally time to get some data from Kentico Cloud and display it on the home page. We’ll be using the .items method and some filtering options which you can read more about here. Change the body of your article_list action to the following:

def article_list
  @response = @@delivery_client.items(
    'system.type'.eq 'article'
  )
  .order_by('elements.post_date', '[desc]')
  .execute
  if @response.http_code == 200
    render partial: "article_tile", collection: @response.items, as: :article
  else
    logger.info @response.to_s
    render html: 'Sorry, articles are not available at this time'
  end
end


So, what’s going on here? The client we defined in ApplicationController is getting all content items from Kentico Cloud of the “article” type and storing them in a variable which is passed to the _article_tile.html.erb file. If the response is successful, we render the view for each content item, which will be accessible in the partial view as article. Otherwise, we log some data about the response and render plain HTML instead.

Change the _article_tile.html.erb partial to render a preview of each article and link to another page to read the full article:

<a style="color:black" href="/article/<%= article.system.codename %>">
 <div style="background-color:#eee;float:left;padding:10px;width:300px;height:400px;margin-bottom:20px;margin-right:20px;display:inline-block">
 <span style="font-weight:bold;font-size:1.3em"><%= article.elements.title.value %></span>
 <br><span style="color:#888"><%= DateTime.parse(article.elements.post_date.value).strftime("%A, %B %e, %Y") %></span>
 <br/><br/><img src=<%= article.get_assets('teaser_image').first.url %> style="width:100%" />
 <br/><span><%= article.elements.summary.value %></span>
 </div>
</a>


If you run the server now, the home page should look like this:

ruby-articles


Resolving Rich Text

Rich text elements, such as the one in our articles, can contain links to other content items, components, and many other things. We’ll now create a page that will display the article text, resolving any of these objects contained in the rich text field.

First, create ArticleController in /app/controllers which will use the codename of the article from the request to get the content item from Kentico Cloud. A URL such as ~/article/some_code_name will automatically map to the controller’s show() action due to default routing rules.

class ArticleController < ApplicationController
  def show
    codename = params[:id]
    response = @@delivery_client.item(codename).execute
    if response.http_code == 200
      @article = response.item
      render partial: 'show'
    else
      logger.info response.to_s
      render html: 'The article you requested couldn\'t be found'
    end
  end
end


Register this controller in /app/config/routes.rb:

Rails.application.routes.draw do
  resources :home, :article
  get :article_list, :controller => :home
  root 'home#index'
end


Now, create the _show.html.erb partial view in /app/views/article:

<h1><%= @article.elements.title.value %></h1>
<%= @article.elements.body_copy.value.html_safe %>


If you run rails server now and access an article that contains inline content items (e.g. /articles/ coffee_beverages_explained), will notice that the inline content items are rendered with their <object> tags:

<object type="application/kenticocloud" data-type="item" data-rel="component" data-codename="n373888cc_34e2_01e1_1820_3cb52ab1b2a1"></object>


This is meant to be a Hosted Video component, but we need to use the InlineContentItemResolver to change how it appears on our site. Change /app/controllers/ApplicationController to use an inline item resolver:

class ApplicationController < ActionController::Base
  PROJECT_ID = '<your-project-id>'.freeze
  item_resolver = KenticoCloud::Delivery::Resolvers::InlineContentItemResolver.new(lambda do |item|
    if (item.system.type.eql? 'hosted_video') && (item.elements.video_host.value[0].codename.eql? 'youtube')
      return "<iframe class='hosted-video__wrapper'
                     width='560'
                     height='315'
                     src='https://www.youtube.com/embed/#{item.elements.video_id.value}'
                     frameborder='0'
                     allowfullscreen
                     >
             </iframe>"
    else
      return ''
    end
  end)
  @@delivery_client = KenticoCloud::Delivery::DeliveryClient.new project_id: PROJECT_ID,
                                                                 inline_content_item_resolver: item_resolver
end


As this GitHub project states, to get the resolved value for an element you need to use the get_string method. Change the _show.html.erb partial to use this method:

<h1><%= @article.elements.title.value %></h1>
<%= @article.get_string('body_copy').html_safe %>


If you now access /article/coffee_beverages_explained, you’ll see the YouTube video in the article:

ruby-youtube


Resolving Links

If a rich text element contains links to other content items, they will be rendered as empty <a> tags by default; you can see an example of this on the /article/coffee_processing_techniques page of your application. To specify the URLs to other pages on your site, implement a ContentLinkResolver.

In /app/controllers/application_controller.rb, register a ContentLinkResolver similarly to the way the InlineContentItemResolver was created:

link_resolver = KenticoCloud::Delivery::Resolvers::ContentLinkResolver.new(lambda do |link|
  return "/coffees/#{link.url_slug}" if link.type.eql? 'coffee'
  return "/article/#{link.code_name}" if link.type.eql? 'article'
end)
@@delivery_client = KenticoCloud::Delivery::DeliveryClient.new project_id: PROJECT_ID,
                                                               inline_content_item_resolver: item_resolver,
                                                               content_link_url_resolver: link_resolver


If you access /article/coffee_processing_techniques now, the links to coffees on your site will correctly point to other pages such as /coffees/kenya-gakuyuni-aa (though, we haven’t created the needed controllers).

Success!

You now have a very basic Rails application! This should provide the foundation for developing your next cool Rails project with Kentico Cloud. Feel free to stop by the Ruby SDK repository to read the documentation, submit issues or feature requests, and more: https://github.com/Kentico/delivery-sdk-ruby.