README.md in renderful-0.2.0 vs README.md in renderful-0.3.0

- old
+ new

@@ -1,11 +1,11 @@ # Renderful -[![CircleCI](https://circleci.com/gh/bestmadeco/renderful.svg?style=svg)](https://circleci.com/gh/bestmadeco/renderful) +[![CircleCI](https://circleci.com/gh/nebulab/renderful.svg?style=svg)](https://circleci.com/gh/nebulab/renderful) -Welcome! Renderful is a rendering engine for [Contentful](https://www.contentful.com) spaces. It -allows you to map your content types to Ruby objects that take care of rendering your content. +Welcome! Renderful is a rendering engine for headless CMSs. It allows you to map your content types +to Ruby objects that take care of rendering your content. ## Installation Add this line to your application's Gemfile: @@ -26,261 +26,202 @@ ``` Once you have installed the gem, you can configure it like this: ```ruby -contentful = Contentful::Client.new( - space: 'CONTENTFUL_SPACE_ID', - access_token: 'CONTENTFUL_ACCESS_TOKEN', +RenderfulClient = Renderful::Client.new( + provider: Renderful::Provider::DummyCms.new(api_key: 'secretApiKey'), # see "Providers" + components: { + 'jumbotron' => JumbotronComponent, + }, ) +``` -renderful = Renderful.new( - contentful: contentful, - renderers: { - 'jumbotron' => JumbotronRenderer, - } -) -``` - ## Usage Suppose you have the `jumbotron` content type in your Contentful space. This content type has the `title` and `content` fields, both strings. -Let's create the `app/renderers/jumbotron_renderer.rb` file: +Let's create the `app/components/jumbotron_component.rb` file: ```ruby -class JumbotronRenderer < Renderful::Renderer +class JumbotronComponent < Renderful::Component def render <<~HTML <div class="jumbotron"> - <h1 class="display-4"><%= entry.title %></h1> - <p class="lead"><%= entry.content %></p> + <h1 class="display-4">#{ entry.title }</h1> + <p class="lead">#{ entry.content }</p> </div> HTML end end ``` -You can now render this component by retrieving it from Contentful and rendering it with Renderful: +You can now render the component like this: ```ruby -entry = contentful.entry('jumbotron_entry_id') -renderful.render(entry) +RenderfulClient.render('my_entry_id') ``` -### Rich text rendering - -If you have rich-text fields, you can leverage Contentful's [rich_text_renderer](https://github.com/contentful/rich-text-renderer.rb) -along with a custom local variable: - -```ruby -class TextBlockRenderer < Renderful::Renderer::Rails - def html_body - RichTextRenderer::Renderer.new.render(entry.body) - end - - def locals - { html_body: html_body } - end -end -``` - -Then, just reference the `html_body` variable as usual: - -```erb -<%# app/views/renderful/_text_block.html.erb %> -<%= raw html_body %> -``` - -### Nested components - -What if you want to have a `Grid` component that can contain references to other components? It's -actually quite simple! Simply create a _References_ field for your content, then recursively render -all of the content entries contained in that field: - -```ruby -# app/components/grid.rb -class Grid < Renderful::Renderer - # This will define a `resolved_blocks` method that reads external references - # from the `blocks` fields and turns them into Contentful::Entry instances - resolve :blocks - - def render - entries = blocks.map do |block| - # `client` can be used to access the Renderful::Client instance - <<~HTML - <div class="grid-entry"> - #{client.render(block)} - </div> - HTML - end - - <<~HTML - <div class="grid">#{entries}</div> - HTML - end -end -``` - ### Caching -You can easily cache the output of your renderers by passing a `cache` key when instantiating the -client. The value of this key should be an object that responds to the following methods: - -- `#read(key)` -- `#write(key, value)` -- `#delete(key)` -- `#exist?(key)` +You can easily cache the output of your components. A Redis cache implementation is included out of +the box. Here's an example: -A Redis cache implementation is included out of the box. Here's an example: - ```ruby -renderful = Renderful.new( - contentful: contentful, +RenderfulClient = Renderful.new( cache: Renderful::Cache::Redis.new(Redis.new(url: 'redis://localhost:6379')), - renderers: { - 'jumbotron' => JumbotronRenderer - } + # ... ) -``` +``` If you are using Rails and want to use the Rails cache store for Renderful, you can simply pass `Rails.cache`, which responds to the expected interface: ```ruby -renderful = Renderful.new( - contentful: contentful, +RenderfulClient = Renderful.new(ful, cache: Rails.cache, - renderers: { - 'jumbotron' => JumbotronRenderer - } + # ... ) -``` +``` #### Cache invalidation -The best way to invalidate the cache is through [Contentful webhooks](https://www.contentful.com/developers/docs/concepts/webhooks/). +The best way to invalidate the cache is through [webhooks](https://www.contentful.com/developers/docs/concepts/webhooks/). Renderful ships with a framework-agnostic webhook processor you can use to automatically invalidate the cache for all updated content: ```ruby -Renderful::CacheInvalidator.new(renderful).process_webhook(json_body) +RenderfulClient.invalidate_cache_from_webhook(json_body) ``` This is how you could use it in a Rails controller: ```ruby -class ContentfulWebhooksController < ApplicationController +class WebhooksController < ApplicationController skip_before_action :verify_authenticity_token def create - Renderful::CacheInvalidator.new(RenderfulClient).process_webhook(request.raw_post) + RenderfulClient.invalidate_cache_from_webhook(request.raw_post) head :no_content end end ``` The cache invalidator will not only invalidate the cache for the entry that has been updated, but also for any entries linking to it, so that they are re-rendered. This is very useful, for instance, if you have a `Page` entry type that contains references to many UI components - when one of the components is updated, you want the page to be re-rendered. -### Rails integration +### ViewComponent support -If you are using Ruby on Rails and you want to use ERB instead of including HTML in your renderers, -you can inherit from the Rails renderer: +Renderful integrates nicely with [ViewComponent](https://github.com/github/view_component) for +rendering your components: ```ruby -class JumbotronRenderer < Renderful::Renderer::Rails -end +RenderfulClient = Renderful::Client.new( + components: { + 'jumbotron' => JumbotronComponent, # JumbotronComponent inherits from ViewComponent::Base + }, +) +``` + +However, keep in mind you will now have to pass a view context when rendering them: + +```ruby +RenderfulClient.render('my_entry_id', view_context: view_context) ``` -Then, create an `app/views/renderful/_jumbotron.html.erb` partial: +## Providers -```erb -<div class="jumbotron"> - <h1 class="display-4"><%= entry.title %></h1> - <p class="lead"><%= entry.content %></p> -</div> +### Contentful + +In order to integrate with Contentful, you will first need to add the `contentful` gem to your +Gemfile: + +```ruby +gem 'contentful' ``` -As you can see, you can access the Contentful entry via the `entry` local variable. +Now make sure to install it: -#### Custom renderer +```console +$ bundle install +``` -The Rails renderer uses `ActionController::Base.renderer` by default, but this prevents you from -using your own helpers in components. If you want to use a different renderer instead, you can -override the `renderer` method: +Finally, initialize Renderful with the Contentful provider: ```ruby -class JumbotronRenderer < Renderful::Renderer::Rails - def renderer - ApplicationController.renderer - end -end -``` +RenderfulClient = Renderful::Client.new( + provider: Renderful::Provider::Contentful.new( + contentful: Contentful::Client.new( + space: 'cfexampleapi', + access_token: 'b4c0n73n7fu1', + ) + ) +) +``` -#### Custom locals +You can now render your Contentful entries via Renderful: -If you want, you can also add your own locals: +```ruby +RenderfulClient.render('your_entry_id') +``` +### Prismic + +In order to integrate with Prismic, you will first need to add the `prismic.io` gem to your Gemfile: + ```ruby -class JumbotronRenderer < Renderful::Renderer::Rails - def locals - italian_title = entry.title.gsub(/hello/, 'ciao') - { italian_title: italian_title } - end -end +gem 'prismic.io', require: 'prismic' ``` -You would then access them like regular locals: +Now make sure to install it: -```erb -<div class="jumbotron"> - <h1 class="display-4"> - <%= entry.title %> - (<%= italian_title %>) - </h1> - <p class="lead"><%= entry.content %></p> -</div> +```console +$ bundle install ``` -#### Resolution in ERB views +Finally, initialize Renderful with the Prismic provider: -If you need to render resolved fields (as in our `Grid` example), you can use `renderer` and -`client` to access the `Renderful::Renderer` and `Renderful::Client` objects: +```ruby +RenderfulClient = Renderful::Client.new( + provider: Renderful::Provider::Prismic.new( + prismic: Prismic.api('https://yourendpoint.prismic.io/api', 'your_access_token') + ) +) +``` -```erb -<%# app/views/renderful/_grid.html.erb %> -<div class="grid"> - <% renderer.blocks.each do |block| %> - <div class="grid-entry"> - <%= client.render(block) %> - </div> - <% end %> -</div> +You can now render your Prismic documents via Renderful: + +```ruby +RenderfulClient.render('your_entry_id') ``` +NOTE: Due to limitations in Prismic's API, cache invalidation for Prismic will invalidate all your +components. Depending on how often you update your content, you may want to disable caching entirely +if you are using Prismic. + ## Development -After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run -the tests. You can also run `bin/console` for an interactive prompt that will allow you to +After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run +the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. -To install this gem onto your local machine, run `bundle exec rake install`. To release a new -version, update the version number in `version.rb`, and then run `bundle exec rake release`, which -will create a git tag for the version, push git commits and tags, and push the `.gem` file to +To install this gem onto your local machine, run `bundle exec rake install`. To release a new +version, update the version number in `version.rb`, and then run `bundle exec rake release`, which +will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing -Bug reports and pull requests are welcome on GitHub at https://github.com/bestmadeco/renderful. +Bug reports and pull requests are welcome on GitHub at https://github.com/nebulab/renderful. ## License The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). ## Credits -Renderful is sponsored and maintained by [Bolt Threads Inc.](https://www.boltthreads.com). +Renderful was originally developed by [Nebulab](https://nebulab.it) and sponsored by +[Bolt Threads](https://www.boltthreads.com). It is currently maintained by Nebulab.