独立于Rails使用HAML文件中的布局 [英] Using layouts in HAML files independently of Rails

查看:72
本文介绍了独立于Rails使用HAML文件中的布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My end goal is to create several static HTML files for hand-off to other folks.

但是对于我的工作流程,我想将HAML作为基本源文件.这样一来,我希望至少在我这一边干这个过程.

But for my workflow, I'd like to have HAML as the basic source files. In doing so, I'd hope to DRY up the process at least on my side.

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

Now I have a lot of pages that will ultimately be sharing a common layout, and I'm wondering how to incorporate the layouts.

这是我当前的代码:

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

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

./src/home.html.haml

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

现在这显然不起作用,因为在Rails的上下文中未定义render方法,但是我希望它能理解我要尝试做的事情.

Now this clearly doesn't work because the render method is undefined out of the context of Rails, but I hope it gets the point across what I'm trying to do.

有什么建议吗?

推荐答案

您正在混合使用两种不同的Rails功能:部分(使用render)布局(使用yield).

You're mixing up two distinct Rails feature: partials (using render) and layouts (using yield).

您可以将其中一个(或两个)的类似rails的版本添加到仅Haml的程序中.

You can add a rails-like version of either (or both) of them to a Haml only program.

在Rails视图中,您可以使用render :partial_name来使文件_partial_name.html.haml在包含视图中的那个位置呈现(实际上,Rails允许您使用受支持的任何模板语言,并且它将找到正确的文件扩展名)使用,但在这里我只会坚持使用Haml).在Rails之外无法使用render,但是可以很容易地添加它.

In a rails view, you can use render :partial_name to cause the file _partial_name.html.haml to be rendered at that point in the containing view (actually Rails allows you to use any templating language supported and it will find to correct filename extension to use, but I'll stick to just Haml here). Outside of Rails render isn't available, but it can be added fairly easily.

一个简单的render方法将找到合适的haml文件,将其渲染,然后返回要包含在父级中的html字符串:

A simple render method would just find the appropriate haml file, render it, and return the html string for inclusion in the parent:

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方法放在脚本中,然后在模板中这样调用它即可:

The first argument to Haml::Engine.render is a scope object, which we can use to add methods available inside the haml template. It defaults to Object.new. In a simple case like this, however, we can define the render method in the top level, and it will be available in the scope of the Haml template. We simply put our render method in the script before the call to Haml::Engine.new(...).render, and call it like this in our template:

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

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

Now the file _the_partial.html.haml will appear rendered at the appropriate point of the output.

我们可以更进一步. Rails允许您将局部变量的哈希值传递给局部变量. Haml还将接受作为本地变量传递的变量哈希,作为Haml render方法的第二个参数.因此,如果我们将render方法扩展为:

We can take this a step further. Rails allows you to pass in a hash of local variables to a partial. Haml will also accept a hash of variables to be passed as local variables, as the second argument to the Haml render method. So if we expand our render method to look like:

def render(partial, locals = {})
  Haml::Engine.new(File.read("_#{partial}.html.haml")).render(Object.new, locals)
end

我们可以使用类似于以下内容的部分内容:

we can use a partial that looks something like:

%p You passed in #{foo}

,并使用以下模板从我们的模板中调用它:

and call it from our template with:

%body
  =render :partial, :foo => "bar"

将呈现

<body>
  <p>You passed in bar</p>
</body>

布局

在Rails中,您可以为视图指定布局,以便所有页面可以共享相同的布局 标题,菜单区域等.这是通过指定布局文件来完成的,您可以在其中调用yield来呈现所涉及的实际视图.将布局添加到haml时会比较棘手,但仍然可以完成.

Layouts

In Rails, you can specify a layout for your views, so that all your pages can share the same header, menu area etc. This is done by specifying a layout file, within which you call yield to render the actual view in question. Layouts are slightly more tricky to add to haml, but can still be done.

Hamls render方法也接受一个块,因此一个简单的解决方案是呈现布局文件,并传递一个呈现视图文件的块:

Hamls render method also accepts a block, so a simple solution would be to render the layout file, and pass a block that renders the view file:

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的地方呈现.

This would give the contents of layout.html.haml rendered with the contents of view.html.haml rendered where the layout file contained =yield.

尽管如此,Rails更具灵活性.它允许您在布局文件中多次调用yield,分别命名一个特定区域,并在视图中使用content_for方法指定要在每个区域添加的内容.因此,在您的布局文件中:

Rails is a bit more flexible than that though. It allows you to call yield multiple times in your layout file, naming a specific region in each case, and to specify the contents to be added at each region using the content_for method within your views. So in your layout file:

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

并在您看来:

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

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

The way Rails actually works is to render the view part first, storing all the different sections, and then rendering the layout, passing a block that provides the appropriate chunk whenever yield is called in the layout. We can replicate this using a little helper class to provide the content_for method and keep track of the rendered chunks for each region:

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方法获得渲染的haml,而不将其直接输出到输出.请注意,这不会捕获视图的未命名部分.

Here we're using the capture_haml method to get the rendered haml without it going direct to the output. Note that this doesn't capture the unnamed part of the view.

我们现在可以使用我们的助手类来呈现最终输出.

We can now use our helper class to render the final output.

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包含最终渲染的输出.

Now the variable output contains the final rendered output.

请注意,这里的代码并不能提供rails随附的所有灵活性,但是希望它足以向您展示从哪里开始自定义Haml以满足您的需求.

Note that the code here doesn't provide all the flexibility that's included with rails, but hopefully it's enough to show you where to start customising Haml to meet your needs.

这篇关于独立于Rails使用HAML文件中的布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆