私の最終目標は、他の人に渡すためのいくつかの静的HTMLファイルを作成することです。
しかし、私のワークフローでは、基本的なソースファイルとしてHAMLを使用したいと思います。そうすることで、少なくとも私の側では、プロセスをDRYアップすることを望んでいます。
現在、最終的に共通のレイアウトを共有するページがたくさんあり、レイアウトをどのように組み込むのか疑問に思っています。
これが私の現在のコードです:
#!/usr/bin/env Ruby
require 'rubygems'
require 'rake'
require 'haml'
FileList.new('./src/*.html.haml').each do |filename|
if filename =~ /([^\/]+)\.haml$/
File.open($1, 'w') do |f|
f.write Haml::Engine.new(File.read(filename)).render
end
end
end
!!!
%html
%head
%title Yay
%body
= yield
= render :layout => 'header' do
%p This is awesome
レンダリングメソッドがRailsのコンテキスト外で定義されていないため、これは明らかに機能しませんが、私がやろうとしていることを理解できることを願っています。
助言がありますか?
2つの異なるRails機能: partials(render
を使用) と layouts(yield
を使用)を混同しています) 。
それらのいずれか(または両方)のRailsのようなバージョンをHamlのみのプログラムに追加できます。
Railsビューでは、_render :partial_name
_を使用して、ファイル__partial_name.html.haml
_を包含ビューのその時点でレンダリングできます(実際にはRailsは、サポートされている任意のテンプレート言語を使用でき、使用するファイル名拡張子を修正することができますが、ここではHamlだけに固執します。Rails render
は利用できませんが、かなり簡単に追加できます。
単純なrender
メソッドは、適切なhamlファイルを見つけてレンダリングし、親に含めるためのhtml文字列を返すだけです。
_def render(partial)
# assuming we want to keep the Rails practice of prefixing file names
# of partials with "_"
Haml::Engine.new(File.read("_#{partial}.html.haml")).render
end
_
_Haml::Engine.render
_の最初の引数はスコープオブジェクトであり、hamlテンプレート内で使用可能なメソッドを追加するために使用できます。デフォルトは_Object.new
_です。ただし、このような単純なケースでは、トップレベルでrender
メソッドを定義でき、Hamlテンプレートのスコープで使用できるようになります。 Haml::Engine.new(...).render
を呼び出す前に、スクリプトにrender
メソッドを配置し、テンプレートで次のように呼び出します。
_!!!
%html
%head
%title Hello
%body
=render :the_partial
_
これで、ファイル__the_partial.html.haml
_が出力の適切なポイントにレンダリングされて表示されます。
これをさらに一歩進めることができます。 Railsは、 ローカル変数 のハッシュをパーシャルに渡すことができます。Hamlは、2番目の引数として、ローカル変数として渡される変数のハッシュも受け入れます。 Haml render
メソッドに変換します。したがって、renderメソッドを展開して次のようにすると:
_def render(partial, locals = {})
Haml::Engine.new(File.read("_#{partial}.html.haml")).render(Object.new, locals)
end
_
次のようなパーシャルを使用できます。
_%p You passed in #{foo}
_
テンプレートから次のように呼び出します。
_%body
=render :partial, :foo => "bar"
_
レンダリングされます
_<body>
<p>You passed in bar</p>
</body>
_
Railsでは、ビューのレイアウトを指定して、すべてのページが同じヘッダー、メニュー領域などを共有できるようにすることができます。これは、レイアウトファイルを指定することによって行われます。レイアウトファイル内でyield
を呼び出して実際のレンダリングを行います。問題のビュー。レイアウトはhamlに追加するのが少し難しいですが、それでも実行できます。
Hamls render
メソッドもブロックを受け入れるため、簡単な解決策は、レイアウトファイルをレンダリングし、ビューファイルをレンダリングするブロックを渡すことです。
_Haml::Engine.new(File.read("layout.html.haml")).render do
Haml::Engine.new(File.read("view.html.haml")).render
end
_
これにより、レイアウトファイルに_layout.html.haml
_が含まれている場所でレンダリングされた_view.html.haml
_のコンテンツでレンダリングされた_=yield
_のコンテンツが得られます。
ただし、Railsはそれよりも少し柔軟性があります。レイアウトファイルでyield
を複数回呼び出し、それぞれに特定の領域に名前を付け、ビュー内の_content_for
_メソッドを使用して各領域に追加するコンテンツを指定できます。したがって、レイアウトファイルでは次のようになります。
_!!!
%html
%head
= yield :title
%body
=yield
_
そしてあなたの見解では:
_-content_for :title do
%title Hello
%p
Here's a paragraph.
_
Railsが実際に機能する方法は、最初にビューパーツをレンダリングし、すべての異なるセクションを保存してから、レイアウトをレンダリングし、yield
が常に適切なチャンクを提供するブロックを渡すことです。レイアウトで呼び出されます。小さなヘルパークラスを使用してこれを複製し、_content_for
_メソッドを提供し、各領域のレンダリングされたチャンクを追跡できます。
_class Regions
def initialize
@regions_hash={}
end
def content_for(region, &blk)
@regions_hash[region] = capture_haml(&blk)
end
def [](region)
@regions_hash[region]
end
end
_
ここでは、 _capture_haml
_ method を使用して、出力に直接移動せずにレンダリングされたhamlを取得しています。これは、ビューの名前のない部分をキャプチャしないことに注意してください。
これで、ヘルパークラスを使用して最終出力をレンダリングできます。
_regions = Regions.new
unnamed = Haml::Engine.new(File.read("view_named.html.haml")).render(regions)
output = Haml::Engine.new(File.read("layout_named.html.haml")).render do |region|
region ? regions[region] : unnamed
end
_
これで、変数output
に最終的にレンダリングされた出力が含まれます。
ここのコードは、Railsに含まれているすべての柔軟性を提供するわけではありませんが、ニーズに合わせてHamlのカスタマイズを開始する場所を示すだけで十分であることに注意してください。
content = Haml::Engine.new(content_haml).render(
Object.new,
:local_var_1 => ...,
:local_var_2 => ...
)
Haml::Engine.new(layout_haml).render(Object.new, :content => content)
layout.haml
!!!
%html
%head
%title
%body
= content
Object.new
のインスタンス変数(意味のあるオブジェクトに置き換える)をhamlで使用することもできます。