Alessandro Rodi
Posted on April 4, 2022
At Renuo we often need an HeadlessCMS in our Ruby On Rails projects, and in the last years, we had a great experience using Dato CMS.
So we decided to release our DatoCMS client open source.
We extracted and isolated the features that we considered most useful and this tutorial will explain you, step-by-step, how to start using it.
DatoCMS setup
We provide a template for a dato backend that you can use for this tutorial:
Use the button above to setup a first DatoCMS project, proceed to the Settings->API Tokens and fetch your ReadOnly API token that we'll use afterwards.
Project setup
The gem expects you to have the following:
- a Rails app 😄
turbo
ViewComponents
Only Rails is an actual requirement, but to use 100% of the features provided by the gem, you'll need also view_components
and turbo
.
Given that you are using Rails >= 7, you can follow these commands
rails new dato-rails-demo --skip-active-record
cd dato-rails-demo
Add to your Gemfile:
gem 'dotenv-rails', groups: [:development, :test]
gem 'view_component'
gem 'dato-rails', require: 'dato'
then run again:
bundle install
echo "DATO_API_TOKEN=<YOUR_DATO_API_TOKEN>" > .env
to install the new libraries and set your Api Token.
Well done. You should be able to simply run bin/rails s
and access your application.
Your first query
The provided project contains Homepage. We'll try to fetch it. DatoCMS provides a GraphQL API Explorer that is very useful to generate queries.
We'll start simple with:
# app/services/dato/queries.rb
module Dato
module Queries
def homepage_query
GQLi::DSL.query {
homepage {
id
}
}
end
end
end
where we define a query to fetch the homepage id.
You need to restart your server here, since we added a new services folder.
We should always have tests for our queries. Such a test looks like this:
# test/services/dato/queries_test.rb
require "test_helper"
class DatoQueriesTest < ActiveSupport::TestCase
include Dato::Queries
test 'homepage_query' do
client = Dato::Client.new
response = client.execute(homepage_query)
assert_not_nil response.data.homepage.id
end
end
If you have a green test, it means your are already successfully fetching your homepage from DatoCMS.
Render fetched data
We can now generate a controller and a component and we'll render the data that we just fetched.
rails g controller HomepageController
rails g component Homepage
A component is not mandatory, you can also use standard partials, but it will be necessary to benefit of more advanced features like live reloading afterwards.
# app/components/homepage_component.rb
class HomepageComponent < ViewComponent::Base
def initialize(data)
super
@data = data
end
end
# app/components/homepage_component.html.erb
<div>This is the homepage id: <%= @data.homepage.id %></div>
# app/controllers/homepage_controller.rb
class HomepageController < ApplicationController
include Dato::Queries
def show
client = Dato::Client.new
response = client.execute(homepage_query)
render HomepageComponent.new(response.data)
end
end
# config/routes.rb
Rails.application.routes.draw do
root "homepage#show"
end
Structured Text
One of the most important fields that you are going to use on DatoCMS is the Structured Text.
You can easily fetch and render it using dato-rails
.
Update your homepage query:
def homepage_query
GQLi::DSL.query {
homepage {
id
content {
value
blocks {
__typename
id
image {
responsiveImage(imgixParams: {fm: __enum("png")}) {
___ Dato::Fragments::ResponsiveImage
}
}
}
}
}
}
end
the code above fetches also the content
field that we use in the homepage and we pre-filled in the example.
Here is how you render a Structured Text field:
<div>This is the homepage id: <%=@data.homepage.id %></div>
<%= render Dato::StructuredText.new(@data.homepage.content) %>
The library provides you a component that you can use to render already everything. You will now see the following:
Custom blocks
In the example above, you see that a block was defined in the blocks library of the example. Such blocks are created by you, so the library cannot provide a component to render them, but you need to create one yourself, with the information available. Read the output of the page for more information and instructions on how to define your component.
We will have:
# app/components/dato/image_block_record.html.erb
<%= render Dato::ResponsiveImage.new(@node.image.responsiveImage) %>
# app/components/dato/image_block_record.rb
module Dato
class ImageBlockRecord < Dato::Node
end
end
you can now simply reload the page, and your block will be rendered correctly with a responsive image.
Customizations
Let's start by adding simple.css to our application.html.erb
header so that it looks better:
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
If you want to override how a Structured Text node is rendered you have two possibilities:
CSS only
The nodes contain HTML classes that you can use to customize the look and feel of each node by working only with CSS.
.dato-cms-paragraph {
margin-top: 30px;
}
will add 30px margin top to all the paragraphs nodes.
Override the component
We cannot unfortunately override only the template at the moment. So if you want to customize your node further, you'll need to do the following:
- Define a new component. Let's define a new component for the cite block
# app/components/dato/fancy_cite.rb
class Dato::FancyCite < Dato::DastNode
def initialize(node, root)
super(node, "blockquote", root)
end
end
# app/components/dato/fancy_cite.html.erb
<blockquote>
<% @node.children&.each do |node| %>
<%= render_node(node) %>
<% end %>
<p>
<cite>– <%= @node.attribution %></cite>
</p>
</blockquote>
# config/initializers/dato.rb
Dato::Config.overrides = {
blockquote: 'Dato::FancyCite'
}.with_indifferent_access
Since we added an initializer, restart the server.
This is how you override completely a node.
Preview mode
When using the draft/published feature of Dato CMS, you can fetch the draft version of your model when using the client. We will change the controller as follow:
client = Dato::Client.new(preview: params[:preview].present?)
and enable Draft/Preview for our Homepage model.
Proceed to the Settings of the project, and then models, select the Homepage model, and click Edit Model.
Now you can check how the page looks like when passing the preview
parameter in the URL and you perform changes on the Homepage. Head to http://localhost:3000?preview=true.
Real Time Mode
Working on DatoCMS to edit your homepage and going back and forth to your website and hit "refresh" every time, might be tedious and time consuming. Real Time Mode is one of the most interesting features of Dato and you can benefit from it also when using Rails.
The only thing you need to do is to wrap your component into a Dato::Live
component and mount the routes.
We'll change the controller action as follows:
def show
render Dato::Live.new(HomepageComponent,
homepage_query,
preview: params[:preview].present?,
live: params[:live].present?)
end
And mount the engine routes:
# config/routes.rb
Rails.application.routes.draw do
root "homepage#show"
mount Dato::Engine => '/dato'
end
Head to your page and add the parameters ?live=true&preview=true
to the URL and enjoy live reloading.
Posted on April 4, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.