-
Notifications
You must be signed in to change notification settings - Fork 20
Storing templates in the database
Bryce Thornton edited this page Jul 22, 2013
·
3 revisions
Say you allow your users to have a custom template for posts/show
. Prepend a template resolver to your view path using prepend_view_path
:
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
prepend_view_path CustomTemplateResolver.new
def show
# It's probably a good idea to have a default template at
# `app/views/posts/show.html.curly`.
@post = Post.find(params[:id])
end
protected
# This is the tricky part - in order to get data into your
# template resolver, you need to register a template detail.
# This needs to be an array. The block returns a default value.
ActionView::LookupContext.register_detail(:accounts) { [] }
# This is called by Rails to get the actual details:
def details_for_lookup
# You could also use e.g. `themes`.
{ accounts: [current_account] }
end
end
Make sure there's a presenter with a matching name:
# app/presenters/posts/show_presenter.rb
class Posts::ShowPresenter < Curly::Presenter
presents :post
def title
@post.title
end
end
The resolver is the final part, and can be a bit tricky:
# app/models/custom_template_resolver.rb
class CustomTemplateResolver < ActionView::Resolver
def find_templates(name, prefix, partial, details)
account = details.fetch(:accounts).first
source = account.template
name = "_#{name}" if partial
path = [prefix, name].compact.join("/")
# This needs to be different for each template. Perhaps
# use a digest of the template source.
identifier = ["template", account.id].join("-")
# Get the Curly handler
handler = ActionView::Template.handler_for_extension(:curly)
details = {
format: :html,
updated_at: account.updated_at, # important if you want to
# cache the compiled templates.
virtual_path: path
}
# Return a new template object wrapped in an array
[ActionView::Template.new(source, identifier, handler, details)]
end
end
We found this to be a much better fit than using the Liquid style rendering. Since we're using Rails' own template resolution system, we can render partials inside the presenters, and caching just works.