Build your first Ruby on Rails app
Create a basic Ruby on Rails app using the Delivery Ruby SDK.You’ll practice what you’ve learned in the previous lessons.
Create a new project
Prepare the environment
To begin your project, you’ll need Ruby 3.1 and Rails installed. You can get Ruby from ruby-lang.org. After that, install Rails using this command:gem install rails
Create a blank Rails project
To create a new Rails project, we recommend using the–O
parameter, which will create the project without a database. In this tutorial, you won't need a local database.
rails new kontentairails –O
Gemfile
. Inside the file, you'll add Ruby gems that your project needs to run.
Add dependencies
In theGemfile
file, add the kontent-ai-delivery
gem, and also the render_async
gem like this:
gem 'kontent-ai-delivery'
gem 'render_async'
First run
At this point, you can run your Rails application by executing the following commands in your command line.bundle install
rails server
localhost:3000
in your browser and you'll see the default Rails welcome page:
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 you can use the Kontent::Ai::Delivery::DeliveryClient
in your controllers:
class ApplicationController < ActionController::Base
PROJECT_ID = '<YOUR_ENVIRONMENT_ID>'.freeze # PROJECT_ID identifies a project environment
@@delivery_client = Kontent::Ai::Delivery::DeliveryClient.new project_id: PROJECT_ID
end
home_controller.rb
in the same directory. You'll use the controller to display a list of articles on the home page.
class HomeController < ApplicationController
def index; end
end
index.html.erb
. You’ll add the cool stuff in a bit!
In the /app/views
directory, create a new folder named home. Then create the index.html.erb
file inside of it. You can add any HTML you want here. For tutorial purposes, let's use a placeholder for your list of articles.
<h1>Latest Dancing Goat Articles</h1>
<div>
(coming soon)
</div>
/app/config/routes.rb
file and register our HomeController
. Then tell Rails you want to view HomeController
’s index()
action when accessing the main domain.
Rails.application.routes.draw do
resources :home
root 'home#index'
end
rails server
command again to view your changes. There are no articles displaying yet, so let’s fix that.
Asynchronous rendering
You’re going to add a new action to theHomeController
that will asynchronously request articles from Kontent.ai 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 Kontent.ai 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 this tutorial, you’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 the app/views/layouts/application.html.erb
file just above the closing </body>
tag.
<body>
<%= yield %>
<%= content_for :render_async %>
</body>
app/views/home/index.html.erb
file you need to tell render_async
where to load your list of articles.
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>
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
like this:
Rails.application.routes.draw do
resources :home
get :article_list, :controller => :home
root 'home#index'
end
article_list
action in your HomeController
. This action will render a partial view when called.
class HomeController < ApplicationController
def index; end
def article_list
render partial: "article_tile"
end
end
_article_tile.html.erb
in the app/views/home
folder which will render when the article_list
action is called. It can contain anything right now.
<b>Articles are almost here..</b>
rails server
and reload the home page.
The render_async
has rendered _article_tile.html.erb
view within the index view.
Now for the fun stuff!
Adding Rails to Kontent.ai
It’s finally time to get some data from Kontent.ai and display it on the home page. You’ll be using the .items method and a few filtering options. Change the body of yourarticle_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
ApplicationController
controller is getting all content items from Kontent.ai 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, the app renders the view for each content item, which will be accessible in the partial view as article. Otherwise, the app logs some data about the response and renders plain HTML instead.
Change the _article_tile.html.erb
partial view 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>
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. You’ll now create a page that will display the article text, resolving any of these objects contained in the rich text field. First, create theArticleController
controller in /app/controllers
which will use the codename of the article from the request to get the content item from Kontent.ai. A URL such as ~/article/some_code_name
will automatically map to the controller’s show()
action thanks 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
/app/config/routes.rb
.
Rails.application.routes.draw do
resources :home, :article
get :article_list, :controller => :home
root 'home#index'
end
_show.html.erb
partial view in /app/views/article
.
<h1><%= @article.elements.title.value %></h1>
<%= @article.elements.body_copy.value.html_safe %>
rails server
now and access an article that contains inserted content items (e.g. /articles/ coffee_beverages_explained
), you'll notice that the these content items are rendered with their <object>
HTML tags like this.
<object type="application/kenticocloud" data-type="item" data-rel="component" data-codename="n373888cc_34e2_01e1_1820_3cb52ab1b2a1"></object>
InlineContentItemResolver
to change how it appears in the app. Change /app/controllers/ApplicationController
to use an inline item resolver.
class ApplicationController < ActionController::Base
PROJECT_ID = '<YOUR_ENVIRONMENT_ID>'.freeze # PROJECT_ID identifies a project environment
item_resolver = Kontent::Ai::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 = Kontent::Ai::Delivery::DeliveryClient.new project_id: PROJECT_ID, inline_content_item_resolver: item_resolver
end
get_string
method. Change the _show.html.erb
partial view to use the method.
<h1><%= @article.elements.title.value %></h1>
<%= @article.get_string('body_copy').html_safe %>
/article/coffee_beverages_explained
route in your browser, you’ll see the YouTube video rendered correctly in the article detail.
Resolving links
Sign in with your Kontent.ai credentials or sign up for free to unlock the full lesson, track your progress, and access exclusive expert insights and tips!