ActionView を単体で使ってみる」というのを書いたので、ついでにいろいろ試してみる。その1。

誰が得するのか謎だけど ActionView だけで slim を使うことを試みてみました。 action_viewを require して、 action_pack を require して、 slim を require すれば使えます。

用意したファイル

  • views/prefix/slim.html.slim
p
  | Hello, #{@name}
  • views/layout/appliacation.html.erb
--
<%= yield %>
--
require 'action_view'
require 'action_pack'
require 'slim'

lookup_context = ActionView::LookupContext.new('./views')
lookup_context.cache = false   # ActionPachk を読まなくて済む魔法

view_context = ActionView::Base.new(lookup_context)
view_context.assign(name: 'eiel')
ret = view_context.render(template: 'slim',
                          prefixes: 'prefix',
                          
puts ret

=begin
--
<p>Hello, eiel</p>
--
=end

slim は temple という gem を使ってRailsに対応してました。 ActionPack はバージョン確認に利用しているだけなので、ちょっといじればなんとかなりそうですけど。

もう少し詳しく

誰得感がひどいのでもうちょっと書いてみる。

Railsとの連携の処理の部分は

Temple::Templates::Rails(Slim::Engine,
  :register_as => :slim,
  # Use rails-specific generator. This is necessary
  # to support block capturing and streaming.
  :generator => Temple::Generators::RailsOutputBuffer,
  # Disable the internal slim capturing.
  # Rails takes care of the capturing by itself.
  :disable_capture => true,
  :streaming => defined?(::Fiber))

そうすると Temple::Template#method_missing が呼ばれてます。

def self.method_missing(name, engine, options = {})
  const_get(name).create(engine, options)
end

変数を置き換えてみると

Temple::Templates::Rails.create(Slim::Engin,
  register_as: :slim,
  generator: Temple::Generators::RailsOutputBuffers,
  disable_caputre: true,
  streaming: defined?(::Fiber))

Temple::Templates::Rails.createregister_as: :slim 呼ばれることがわかります。

def create(engine, options)
  register_as = options.delete(:register_as)
  template = Class.new(self)
  template.disable_option_validator!
  template.default_options[:engine] = engine
  template.default_options.update(options)
  template.register_as(*register_as) if register_as
  template
end

そうすると Temple::Templates::Rails.register_asActionViewActionView::Template.register_template_handler を呼びだされて、ActionView で利用できるようになります。

names には [:slim] が束縛されることになります。

def self.register_as(*names)
  names.each do |name|
    ActionView::Template.register_template_handler name.to_sym, new
  end
end

まとめ

ActionViewにテンプレートエンジンを追加するには ActionView::Template.register_template_handler 使うことがわかりました。

ちなみに Rails のリポジトリを検索するとこんな感じでした。

base.register_default_template_handler :erb, ERB.new
base.register_template_handler :builder, Builder.new
base.register_template_handler :raw, Raw.new
base.register_template_handler :ruby, :source.to_proc

関連