Ruby on Rails tutorial: Getting started with Contentful
Tags: ruby, cms, tutorial, rails
Published: 2022-09-16 14:14:13

**NOTE**: This article originally appeared on the [Contentful Blog](https://www.contentful.com/blog/)

Ruby on Rails, often shortened to Rails, is a Ruby-based Model-View-Controller (MVC) framework for building production-ready web applications and services. Rails provides several out-of-the-box features, such as database migrations and ActiveRecord (ORM), to assist developers as they build applications in minimal time. 

Rails shares several similarities with Django, a Python web development framework. However, unlike Django, Rails allows developers to build the controller-specific logic of their application. They also share the convention-over-configuration philosophy and provide standard practices for developers to follow.

Developers building applications with Rails will benefit from leveraging the existing functionalities of gems created by members of the Rails community. For an improved developer experience, Contentful provides several gems that make interacting with its API easier.

To demonstrate how Contentful integrates with Rails, this article will guide you through the process of building a demo job listing application that relies on Contentful for its data. All the sample code is stored on [GitHub for reference](https://github.com/contentful-developer-relations/contentful-ruby-tutorial). 

## Prerequisites 
To follow this tutorial, it’s recommended that you have:

- A Contentful account and access to Contentful UI. If you do not have one, create a [free account](https://www.contentful.com/sign-up/) with a free 60-day trial subscription.
- The Ruby compiler and Ruby on Rails framework installed on your computer.
- A basic familiarity with the Ruby programming language.

## Preparing Contentful resources 
The purpose of our job listing application is to display open job roles to job seekers. Each job listing contains several details, including the job title, description, location, and salary. To structure the data, we need to define these details on Contentful within a content model.

Using the Contentful UI, create a content model that models the fields within a job post. Each job post will be created as a data entry using this content model. For this tutorial, you will use the default Space created for every Contentful account.  

### Creating a Contentful content model

Once you’re logged into Contentful, click the **Content Model** item within the top navigation bar to navigate to the Content Editor page.  

In the **Create new** content type model box, use “jobs” as the content model name, then provide your preferred description.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9ynel5cxv2czje6b0u1.png)

After saving the content model, use the **+ Add fields** button to add the following fields:

- A short text field type named `title` to store the job role within the job ad,
- A rich text field type named `description` to describe the job being posted,
- A short text field type named `salary` to store a salary range for the job role,
- A short text field type named `location` to store the office address,
- A boolean field type named `remote` to indicate whether the job is remote, and
- A media field type named `image` to store a thumbnail of the job role.

Click the **Save** button to save the fields you have added to the content model.

With the content model saved, the next step is to add your first entry.  

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cr71lm5out9wxrygtqtc.png)

### Adding data into the content model 
Data entries for your defined content models are managed through the Content page on Contentful. For the jobs content model, we want to add some data entries to populate the Rails application.  

Navigate to the Content page and create two entries in the jobs content model. Feel free to copy job details from the Contentful career page or use your preferred details.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/islc4amx3nf8rbi4zscj.png)

### Retrieving Contentful API credentials
Contentful provides the [Content Delivery API](https://www.contentful.com/developers/docs/references/content-delivery-api/) (CDA) for developers to retrieve data stored within a Contentful space. To access the API, provide the access token associated with your Contentful space for authentication. Tokens for a Contentful space are managed on the Settings page within the Contentful UI.

Click the **Settings** item within the navigation bar to reveal a dropdown, then click A**PI Keys** to view all API keys for your Contentful space.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbe1bn6wr3vinlhr6ayf.png)

On the next page, click the **Add API Key** button on the right-hand side to create the first access token for the space. 

Leave all fields within the API Key at their default values and record the **Space ID** and **Content Delivery API** - access token values in a secure text editor. In the following section, you’ll use these values while building the frontend of the Ruby project.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bkj3zgl2ur7lk8n5i9hy.png)

At this point, you have created a content model and obtained your Space ID alongside the associated access token. Let’s now build the Rails application to retrieve and display the two entries within the jobs content model.

### Building the Ruby on Rails application

Within this tutorial, you will use Contentful as a [View Helper](https://www.contentful.com/developers/docs/ruby/tutorials/create-your-own-rails-app/#:~:text=Contentful%20as%20a%20View%20Helper) to retrieve entries from your Contentful Space.  

To begin, execute the two commands below to ensure you have Ruby and Rails installed on your computer. 

```bash
ruby --version
rails --version 
```

If you do not have Rails installed, you could either install it following the gem command below or walk through the [GoRails installation guide](https://gorails.com/setup/osx/12-monterey) to install Rails for your OS:

```bash
gem install rails
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bde1eytvklejq7xdaqf3.png)

Next, generate a new application using the Rails CLI with the command below. The --css flag will instruct the Rails installer to use [TailwindCSS](https://tailwindcss.com/) for styling the application layouts.

```bash
rails new contentful-job-ads --css tailwind
```

This command will create several files and folders that make up the Rails application. You will do the most work within this app directory. The [File/folder section](https://guides.rubyonrails.org/getting_started.html#creating-the-blog-application:~:text=File/Folder,Purpose) of the Rails documentation explains the purpose of each file and directory. 

Move into the generated Rails project directory and use [bundle](https://bundler.io/guides/rails.html) to install the two gems below. You’ll use these while building the application.

- The [Contentful gem ](https://rubygems.org/gems/contentful)for wrapping the Content Delivery and Preview APIs from Contentful. You’ll use the gem to access your content entries within Contentful from the Rails app. 
- The [Rich_text_renderer gem](https://rubygems.org/search?query=rich_text_renderer) for displaying the description Rich Text within the jobs content model. 

```bash
cd contentful-job-ads

bundle add contentful rich_text_renderer
```

Using your preferred code editor, open the `contentful-job-ads` project to create and modify existing files in the next section.

### Defining the application route

The Rails application is intended to display a list of all available jobs on the default page immediately after the opening application. To achieve this design,  change the default route within the application from the Rails welcome page to a custom page. 

Open the `routes.rb` file within the `config` directory and add the path below, which matches the jobs function within the root controller.   

```javascript
Rails.application.routes.draw do
 get '/', to: "root#jobs"
end
```

Next, use the Rails CLI to generate a controller named root for the path you defined above:

```bash
rails generate controller root 
```

### Creating a service object 

Service objects are Plain Old Ruby Objects (PORO) created for specific functions. These are where developers keep specific business logic to avoid clogging up a controller with unrelated code.

By default, services aren’t included when you generate a Rails application. Create your first service manually with the following steps:

1. Create a `services` directory within the `contentful-job-ads/app` folder. 
2. Create a `job_service.rb` file and add the code below to build the `JobService` class.

The `JobService` class below contains a constructor method that instantiates the Contentful client and stores the instance in a variable. You’ll use the `contentful_jobs` method to retrieve all entries within the jobs content model, then use the `rich_renderer` method to render the rich text for the job description. 

Replace the `CONTENT_SPACE_ACCESS_TOKEN` and `CONTENTFUL_SPACE_ID` placeholders with the access token and space ID credentials you previously obtained from the Contentful UI. Optionally, you can access these credentials using environment variables to ensure they’re not leaked when the application code enters a public code repository like GitHub. 

```javascript
class JobService
  def initialize
    @client ||= Contentful::Client.new(
    access_token: "CONTENTFUL_SPACE_ACCESS_TOKEN",
    space: "CONTENTFUL_SPACE_ID",
    dynamic_entries: :auto,
    raise_errors: true
  )
  end

def rich_renderer
  @renderer = RichTextRenderer::Renderer.new
end

def contentful_jobs
  @client.entries(content_type: "jobs", include: 2)
end
  end 
```

Next, open the `contentful-job-ads/config/application.rb` file and add the code below into the `Application` class to load the custom services directory.

```bash
config.eager_load_paths << Rails.root.join("app/services")
```

### Creating application view

Create a jobs method within the root controller to instantiate the additional `JobsService` class. The root controller resides in the `app/controllers/root_controller.rb file`.   

```javascript
def jobs
    @job_instance = JobService.new
end
```

Then, create a `jobs.html.erb` file within the `app/views/root` folder for the Rails application to render as its default page. 

Add the code below to the `jobs.html.erb` file: 

```html
<!DOCTYPE html>
<html>
<head>
  <title>All Jobs</title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
  <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  <%= javascript_importmap_tags %>
  <% jobs = @job_instance.contentful_jobs %>
</head>
  <body>
    <div style="width: 80rem;" >
    <nav class="flex flex-col items-center align-center" >
    <div>
    <p class="text-center text-4xl font-semibold" > Work With Us At Contentful! </p>
          <br />
    <p class="text-center text-lg" >
    Together, let's <strong> deliver </strong> the best CMS experience <br /> that  <strong> developers</strong> and digital  <strong> products</strong> can get!
    </p>
    </div>
    </nav>

  <br />
  <br />

<section>
  <div class="flex flex-row justify-between" >
  <div>
  <h1 class="pb-2 text-xl font-semibold" > All Open Roles </h1>
  </div>
  </div>
  <hr />
</section>
<br />

<section>
  <ul>
  <% jobs.each do |product| %>
  <li class="mb-12 pb-2 shadow-xl rounded-lg">
  <div>
  <div class="m-4 flex flex-row justify-between" >
  <div class="flex" >
  <div class="flex items-center  border-2 border-gray-600 mr-3 h-20 w-24 rounded-xl" >
  <img alt="<%= product.title %>" src="https:<%= product.image.url%>" />
    </div>

<div class="mt-2" >
  <p class="font-semibold text-lg mb-2" >
  <%= product.title %>
  </p>

<div class="pt-1 pb-2">
<span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">Engineering</span>
<span class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2"><%= product.salary %></span>
  </div>
  </div>
  </div>

<div class="flex items-center" >
  <div class="text-right" >
  <p > <%= product.location %></p>
  <p > Posted On: <%= product.created_at.strftime("%B %d %Y") %></p>
  </div>
  </div>
  </div>
<hr />
<div class="m-4" >
  <%= @job_instance.rich_renderer.render(product.description).html_safe  %>
  </div>
  </div>

  </li>
    <% end %>
    </ul>
    </section>
  </div>
</body>
</html>
```

To confirm that the application is working, you will start the Rails server to view the application you have built so far. 

Launch a separate terminal window and execute the watch command below to generate the TailwindCSS classes used in the `jobs.html.erb` file. 

```bash
rails tailwindcss:watch
```

Next, in your existing terminal window, run the command below to start the rails server: 

```bash 
rails server 
```

**Note:** Alternatively, you can install [Foreman](https://github.com/ddollar/foreman) on your computer and execute the `./bin/dev` command to simultaneously generate the TailwindCSS classes and also run the Rails server in a single terminal. 

Using your web browser, navigate to the index page of the running Rails application at [local:host3000](https://localhost:3000/). You will see the following:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yy1907wve2ye8isli9ar.png)

## Further functionality
Rails provides other features to extend the basic functionality of the job listing application that we’ve built. 

One notable Rails feature is [Active Record](https://guides.rubyonrails.org/active_record_basics.html), which allows developers to design the model layer of an application. Contentful’s [contentful_model gem](https://rubygems.org/gems/contentful_model) allows you to associate your Rails models with content models.

## Conclusion
Congratulations on building a job listing application that retrieves and displays job entries from a Contentful Space! To build the application, you successfully followed the Contentful as a View Helper approach by creating the Contentful client within a Service Object.

Are you interested in building a related project using Contentful? [Create a free Contentful account](https://www.contentful.com/sign-up/) and begin designing your content model!