我的最终目标是创建几个静态HTML文件,以便交给其他人.

但是对于我的工作流程,我希望HAML作为基本的源文件.这样做的话,我希望至少在我这方面能让这个过程干涸.

现在我有很多页面最终将共享一个公共布局,我想知道如何合并这些布局.

以下是我当前的代码:

/编译.rb

#!/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

/src/layout.html.哈姆

!!!
%html
  %head
    %title Yay
  %body
    = yield

/src/home.html.哈姆

= render :layout => 'header' do
  %p This is awesome

现在,这显然不起作用,因为渲染方法在Rails的上下文之外是未定义的,但我希望它能够理解我正在try 做的事情.

有什么建议吗?

推荐答案

你混淆了两个截然不同的Rails特性:partials (using render)layouts (using 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的第一个参数是scope对象,我们可以使用它添加haml模板中可用的方法.默认值为Object.new.然而,在这样一个简单的例子中,我们可以在顶层定义render方法,它将在Haml模板的范围内可用.我们只需在调用Haml::Engine.new(...).render之前将render方法放在脚本中,然后在模板中这样调用它:

!!!
%html
  %head
    %title Hello
  %body
    =render :the_partial

现在,文件_the_partial.html.haml将出现在输出的适当位置.

局部变量

我们可以更进一步.Rails允许您将local variables的散列传递给一个部分.Haml还将接受作为局部变量传递的变量散列,作为Haml 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中,可以为视图指定布局,这样所有页面都可以共享相同的视图

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的内容,其中布局文件包含=yield,呈现view.html.haml的内容.

内容

不过,这比Rails更灵活.它允许您在布局文件中多次调用yield,在每种情况下命名一个特定区域,并在视图中使用内容方法指定要在每个区域添加的内容.所以在布局文件中:

!!!
%html
  %head
    = yield :title
  %body
    =yield

在你看来:

-内容 :title do
  %title Hello
%p
  Here's a paragraph.

Rails的实际工作方式是首先渲染视图部分,存储所有不同的部分,然后渲染布局,在布局中调用yield时传递一个提供适当块的块.我们可以使用一个小助手类来复制它,以提供内容方法,并跟踪每个区域的渲染块:

class Regions  
  def initialize
    @regions_hash={}
  end

  def 内容(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以满足您的需求.

Ruby相关问答推荐

如何根据数组键对散列键进行排序?

我如何判断哪些模块已混合到一个类中?

如何在两个浮点数之间的范围内最好地创建一个随机浮点数

将方法应用于数组/可枚举中的每个元素

来自 Linux 上的命令队列的并行处理(bash、python、ruby ......随便)

Ruby 中的方法: objects与not?

group_by 在 rails by 2 或更多属性

在 Ruby 中定义 [方括号] 方法是如何工作的?

rspec 是否有比 target.should < 6 更具体的东西?

条件子句中的赋值是好的Ruby风格吗?

如何在Ruby中获取给定月份的天数,占年份?

测试变量是否等于两个值之一

在 Ruby 中查找内存泄漏的原因

默认情况下需要查找的路径是什么?

如何在器上下文中运行 ruby​​ 脚本?

Array.empty 的相反方法是什么?或 [].empty?在Ruby中

Ruby 的 %q / %Q 引用方法的用例是什么?

通过多个分隔符拆分字符串

如何在文件夹及其所有子文件夹中搜索特定类型的文件

JavaScript Array:获取项目的范围