Skip to content

Instantly share code, notes, and snippets.

@sanderhahn
Last active August 29, 2015 14:08
Show Gist options
  • Save sanderhahn/c38e00b685db4b0ea0dd to your computer and use it in GitHub Desktop.
Save sanderhahn/c38e00b685db4b0ea0dd to your computer and use it in GitHub Desktop.
Resolve rails views from the database instead of the filesystem
class ApplicationController < ActionController::Base
cattr_accessor :template_resolver
def self.template_resolver
@template_resolver = @template_resolver || TemplateResolver.new
end
prepend_view_path self.template_resolver
end
create_table "templates", force: true do |t|
t.text "body"
t.string "path"
t.string "format"
t.string "locale"
t.string "handler"
t.datetime "created_at"
t.datetime "updated_at"
end
namespace :template do
task :import => :environment do
Dir.chdir(Rails.root.join('app/views'))
Dir.glob('**/*.erb') do |file|
parts = file.split('.')
handler = parts.pop
format = parts.size > 1 ? parts.pop : 'html'
locale = parts.size > 1 ? parts.pop : Rails.application.config.i18n.default_locale.to_s
path = parts.pop
if path.match /_mailer/
template = Template.find_or_create_by(
handler: handler,
format: format,
locale: locale,
path: path
)
template.body = File.read("#{Dir.pwd}/#{file}")
template.save!
end
end
end
task :export => :environment do
Dir.chdir(Rails.root.join('app/views'))
Template.all.each do |template|
parts = [template.path]
if template.locale != Rails.application.config.i18n.default_locale.to_s
parts << template.locale
end
parts << template.format
parts << template.handler
file = parts.join('.')
body = template.body.encode(template.body.encoding, :universal_newline => true)
File.write("#{Dir.pwd}/#{file}", body)
end
end
end
class Template < ActiveRecord::Base
def self.format_collection
Mime::SET.symbols.map(&:to_s)
end
def self.locale_collection
I18n.available_locales.map(&:to_s)
end
def self.handler_collection
ActionView::Template::Handlers.extensions.map(&:to_s)
end
validates :body, :path, presence: true
validates :format, inclusion: Template::format_collection
validates :locale, inclusion: Template::locale_collection
validates :handler, inclusion: Template::handler_collection
after_initialize do
self.format ||= 'html'
self.locale ||= 'nl'
self.handler ||= 'erb'
end
after_save do
ApplicationController::template_resolver.clear_cache
end
end
class TemplateResolver < ActionView::Resolver
def find_templates(name, prefix, partial, details)
path = Path.build(name, prefix, partial)
Template.where(
path: path.to_s,
locale: details[:locale],
format: details[:formats],
handler: details[:handlers]
).map do |template|
handler = ActionView::Template.handler_for_extension(template.handler)
ActionView::Template.new(
template.body,
"#{template.id}: #{template.path}.#{template.locale}.#{template.format}.#{template.handler}",
handler,
:virtual_path => template.path,
:format => template.format,
:variant => nil,
:updated_at => template.updated_at
)
end
end
end
@emilebosch
Copy link

Nice! Let me try this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment