Skip to content

Commit

Permalink
Add support for #render_in and ViewComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
aldesantis committed Apr 3, 2020
1 parent 737f4d0 commit d95a1e3
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 118 deletions.
63 changes: 11 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class JumbotronComponent < Renderful::Component
end
```

You can now render this component like this:
You can now render the component like this:

```ruby
RenderfulClient.render('my_entry_id')
Expand Down Expand Up @@ -113,64 +113,23 @@ also for any entries linking to it, so that they are re-rendered. This is very u
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 components,
you can inherit from the Rails component:
Renderful integrates nicely with [ViewComponent](https://github.com/github/view_component) for
rendering your components:

```ruby
class JumbotronComponent < Renderful::Component::Rails
end
```

Then, create an `app/views/renderful/_jumbotron.html.erb` partial:

```erb
<div class="jumbotron">
<h1 class="display-4"><%= entry.fields[:title] %></h1>
<p class="lead"><%= entry.fields[:content] %></p>
</div>
```

As you can see, you can access the content entry via the `entry` local variable.

#### Custom renderer

Rails components use `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:

```ruby
class JumbotronComponent < Renderful::Component::Rails
def renderer
ApplicationController.renderer
end
end
RenderfulClient = Renderful::Client.new(
components: {
'jumbotron' => JumbotronComponent, # JumbotronComponent inherits from ViewComponent::Base
},
)
```

#### Custom locals

If you want, you can also add your own locals:
However, keep in mind you will now have to pass a view context when rendering them:

```ruby
class JumbotronComponent < Renderful::Component::Rails
def locals
italian_title = entry.title.gsub(/hello/, 'ciao')
{ italian_title: italian_title }
end
end
```

You would then access them like regular locals:

```erb
<div class="jumbotron">
<h1 class="display-4">
<%= entry.fields[:title] %>
(<%= italian_title %>)
</h1>
<p class="lead"><%= entry.fields[:content] %></p>
</div>
RenderfulClient.render('my_entry_id', view_context: view_context)
```

## Providers
Expand Down
1 change: 0 additions & 1 deletion lib/renderful.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
require 'renderful/provider/prismic'
require 'renderful/client'
require 'renderful/component/base'
require 'renderful/component/rails'
require 'renderful/version'

module Renderful
Expand Down
12 changes: 9 additions & 3 deletions lib/renderful/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ def initialize(provider:, components:, cache: Cache::Null)
@cache = cache
end

def render(entry_id)
def render(entry_id, options = {})
cache.fetch(ContentEntry.build_cache_key(provider, id: entry_id)) do
content_entry = provider.find_entry(entry_id)
component_for_entry(content_entry).render
component = component_for_entry(content_entry)

if component.respond_to?(:render_in)
component.render_in(options.fetch(:view_context))
else
component.render
end
end
end

Expand All @@ -34,7 +40,7 @@ def component_klass_for_entry(content_entry)
end

def component_for_entry(content_entry)
component_klass_for_entry(content_entry).new(content_entry, client: self)
component_klass_for_entry(content_entry).new(entry: content_entry, client: self)
end
end
end
6 changes: 2 additions & 4 deletions lib/renderful/component/base.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
# frozen_string_literal: true

module Renderful
module Component
class Base
attr_reader :entry, :client

def initialize(entry, client:)
def initialize(entry:, client:)
@entry = entry
@client = client
end

def render
raise NotImplementedError
fail NotImplementedError
end
end
end
Expand Down
29 changes: 0 additions & 29 deletions lib/renderful/component/rails.rb

This file was deleted.

9 changes: 6 additions & 3 deletions spec/renderful/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,19 @@
.with(an_instance_of(String))
.and_return(entry)

component = instance_double('Renderful::Component::Base')
allow(component_klass).to receive(:new)
.with(entry, client: client)
.and_return(instance_double('Renderful::Component::Base', render: 'render_output'))
.with(entry: entry, client: client)
.and_return(component)
allow(component).to receive(:render)
.and_return('render_output')
end

context 'when a component has been registered for the provided content type' do
let(:components) { { content_type_id => component_klass } }

it 'renders the content type with its component' do
result = client.render(entry_id)
result = client.render(entry_id, view_context: 'dummy context')

expect(result).to eq('render_output')
end
Expand Down
26 changes: 0 additions & 26 deletions spec/renderful/component/rails_spec.rb

This file was deleted.

0 comments on commit d95a1e3

Please sign in to comment.