Rubyblok

Introduction

Rubyblok is a versatile Ruby gem designed for a Content Management System (CMS) integration. This gem offers an easy way to integrate a visual CMS - Storyblok - into your Rails app, providing you with quality-of-life features.

This integration allows you to edit your content online, preview it in real-time, and publish with just the click of a button.

In addition, Rubyblok provides an abstraction layer and stores all your content locally, reducing data usage and enhancing performance. This enables new functionalities that leverage the local data, such as global content search, sitemaps, and listings. Ultimately, this setup increases resilience by eliminating dependency on external data sources.

Table of Contents

  1. Installation
  2. Getting Started
  3. Rubyblok tags
  4. Rubyblok workflows
  5. Rubyblok webhook
  6. Caching storyblok images
  7. Caching views
  8. Sitemap configuration
  9. How to Run Tests
  10. Guide for Contributing
  11. How to Contact Us
  12. License

Installation

Rubyblok 1.0 works with Rails 6.0 onwards. Run:

bundle add rubyblok

Storyblok account and new space

Click here to create a free acount at Storyblok, the CMS platform where you will have access to the visual and real-time content editing.

Create a new Space, in My Spaces > Add Space. Select the free Community plan by clicking its "Continue" button and give your space a name.

Get your Storyblok API token in your account, at Storyblok Space > Settings > Access tokens page. Copy the "Preview" access level key.

Add the API token to your config/initializers/rubyblok.rb file:

config.api_token = <your API token>

Getting Started

Hello world - Your first Rubyblok page

Let's get started with Rubyblok by creating your first page in three steps. Note that it is important that you have your Storyblok space set up as described above, in the Storyblok account and new space section.

  1. First, you need to run the install generator, which will create the initializer for you:

    rails g rubyblok:install
    
  2. Now let's generate and run a migration to create the pages table and the Page model:

    rails g rubyblok:migration PAGE
    

rails db:migrate


3. Finally, let's generate your first page:
```bash
rails g rubyblok:hello_world PAGE

This will automatically create a new /pages route, a PagesController, views and styling for your hello world page.

For this example, go to the config/initializers/rubyblok.rb file and turn the caching option off:

config.cached = false

Now you have created your first Hello World page! Start your Rails server, access the /pages route and you will be able to see the page.

Activate the visual editor

Here are the steps to configure the visual editor at Storyblok. This allows you to see a preview of your changes in the Storyblok interface as you edit and save.

At Storyblok, select your Space and go to Settings > Visual Editor.

In the "Location (default environment)" input, add your localhost address:

https://localhost:3333

Then we have to create a local proxy. For that, first create a PEM certificate for your localhost:

brew install mkcert
mkcert -install
mkcert localhost

This will create the localhost-key.pem and localhost.pem files.

To run the proxy, use the local-ssl-proxy tool:

npm install local-ssl-proxy -g
local-ssl-proxy --source 3333 --target 3000 --cert localhost.pem --key localhost-key.pem

This will start a proxy server.

By doing this initial setup, you are able to see your first Storyblok page inside your app and edit its content in the Storyblok admin interface 🎉

Rubyblok tags

rubyblok_story_tag

Use this tag to render stories:

# Slug: full_slug of the storyblok story
<%= rubyblok_story_tag(slug) %>

The name of the storyblok block should match the rails partial, ie if the block is named header, it should have a corresponding _header.html.erb partial in the directory defined in config.component_path. The partial is called with a blok local variable which contains the storyblok block properties.

rubyblok_content_tag

It renders content of Text, TextArea, Markdown or Richtext storyblok fields.

<%= rubyblok_content_tag(content) %>

Optionally, you can use the rubyblok_markdown_tag or rubyblok_richtext_tag tags for rendering specific content.

# Markdown text
<%= rubyblok_markdown_tag("this is a **mark** down") %>
# Output: "<p>this is a <strong>mark</strong> down</p>"

# Richtext
text = { 
         "type" => "doc",
         "content" => [
           { "type" => "paragraph",
             "content" => [{ "text" => "this is a richtext", "type" => "text" }]
            }
         ]
       }

<%= rubyblok_richtext_tag text > %> 
# Output: "<p>this is a richtext</p>"

You can prevent rendering content on production by adding a boolean field type with the name "invisible_on_production" to your Storyblok block.

rubyblok_blocks_tag

Use this tag to render more than one component:

<%= rubyblok_blocks_tag(blok.bloks) %>

You can prevent rendering content on production by adding a boolean field type with the name "invisible_on_production" to your Storyblok block.

Updating content manually at the caching layer

In case you need to update the caching layer with new content added to Storyblok, run the following command:

# Slug: full_slug of the storyblok story
storyblok_story = Rubyblok::Services::GetStoryblokStory.call(slug: slug)
<MODEL_NAME>.find_or_create(storyblok_story)

Rubyblok workflows

Non-cached mode (default)

Rubyblok fetches the content via the Storyblok API and the content is not cached locally.

Cached mode

Rubyblok fetches the content from the local database. This mode is useful ie. if you don't want to call the API on every page request or you want to index the content locally. To enable this mode you need to set the cached feature on in the config/initializers/rubyblok.rb file:

config.cached = true

If you want to update the local cache on every page request (ie. the content is not updated via the webhook), you need to set the auto_update feature on in the config/initializers/rubyblok.rb file:

config.auto_update = true

You can also use the rake task rubyblok:create_or_update_content to update the local cache:

rails rubyblok:create_or_update_content # Using the version configured on `Rubyblok.configuration.version`.

or with the version argument (draft or published):

rails rubyblok:create_or_update_content[published]

Storyblok webhook

The Storyblok webhook will be responsible for updating and deleting content in the local database in case of changes. Learn more here.

  1. First generate the webhook controller:

    rails g rubyblok:webhook_controller STORYBLOK_WEBHOOK
    
  2. You need to set the webhook secret used in Storyblok in the config/initializers/rubyblok.rb file:

    config.webhook_secret = 'secret'
    

Caching storyblok images

You can store your storyblok images and videos on your own S3 storage by enabling this rubyblok feature.

  1. First, you need to run the image cache generator, which will create the model file, the uploader file and the carrierwave config file for you:

    rails g rubyblok:image_cache STORYBLOK_IMAGE
    
  2. Add the following gems to your Gemfile:

    bundle add 'carrierwave'
    bundle add 'fog-aws'
    

3. Now let's run a migration to create the `storyblok_images` table:
```bash
rails db:migrate
  1. Finally, enable the image cache feature in the config/initializers/rubyblok.rb file: config.use_cdn_images = true

Please note that it caches only images added as an Asset field type in Storyblok.

Caching views

You can enable fragment caching on rubyblok components by setting the cache_views feature on in the config/initializers/rubyblok.rb file:

config.cache_views = true

Please note that if any of the component partials changes you need to clear the cache.

Sitemap configuration

You can generate a sitemap configuration for your website with the following command:

rails g rubyblok:sitemap_config

This generator will create a sitemap configuration for the sitemap_generator gem and add the gem to your Gemfile in case it's not already there. The sitemap is generated only for cached content. Please make sure that the cached configuration value is true on config/initializers/rubyblok.rb. Open config/sitemap.rb and add your hostname:

# ...

# TODO: Configure your hostname here
SitemapGenerator::Sitemap.default_host = ''

# ...

For example:

# ...

# TODO: Configure your hostname here
SitemapGenerator::Sitemap.default_host = 'https://myhost.com'

# ...

In order to generate your sitemap or customize this configuration, please read the sitemap_generator gem documentation.

How to Run Tests

You can run unit tests for RubyBlok with the following command:

bundle exec rspec

Guide for Contributing

Contributions are made to this repository via Issues and Pull Requests (PRs). Issues should be used to report bugs, request a new feature, or to discuss potential changes before a PR is created.

How to Contact Us

For any inquiries, reach out to us at: [email protected]

License

RubyBlok is released under the MIT License.