使用Haml::Engine和Rails视图助手

8

我有一个Rails应用程序,其中我正在呈现存储在模型属性中的一块Haml内容。在该Haml块中使用Rails视图帮助程序会很好。目前,我正在使用视图帮助程序中的Haml::Engine#render来呈现此模型属性的内容。它足够好用,但我无法使用=link_to等内容。为了说明问题:

irb(main):003:0> haml_text=<<"EOH"
irb(main):004:0" %p
irb(main):005:0"   =image_tag 'someimage'
irb(main):006:0" EOH
=> "%p\n  =image_tag 'someimage'\n"
irb(main):007:0> engine = Haml::Engine.new(haml_text)
=> #<Haml::Engine:0x7fa9ff7f1150 ... >
irb(main):008:0> engine.render
NoMethodError: undefined method `image_tag' for #<Object:0x7fa9ff7e9a40>
        from (haml):2:in `render'
        from /usr/lib/ruby/gems/1.8/gems/haml-3.0.25/lib/haml/engine.rb:178:in `render'
        from /usr/lib/ruby/gems/1.8/gems/haml-3.0.25/lib/haml/engine.rb:178:in `instance_eval'
        from /usr/lib/ruby/gems/1.8/gems/haml-3.0.25/lib/haml/engine.rb:178:in `render'
        from (irb):8

有没有想法如何做到这一点?有更好的建议吗?
3个回答

15

render 方法允许您指定上下文。类似于:

base = Class.new do
  include ActionView::Helpers::AssetTagHelper
  include ApplicationHelper
end.new

Haml::Engine.new(src).render(base)

可以正常工作。


2
然而,Rails的许多辅助函数都依赖于控制器/请求。例如,image_tag将检查主机名(在请求中)。这会导致非常严重的崩溃。 - Marcel Jackwerth

3

Marcel的方向是正确的。但您需要从某个地方获取有效的渲染引擎作用域。我所做的是使用有效的作用域调用helper,像这样:

在my_view/edit.html.haml中:

=my_revertable_field(self, 'hello world')

在application_helper.rb中
def my_revertable_field(haml_scope, title, field)
      template =<<EOS
.field
  #{label}
  = text_field_tag #{field.name}, #{field.amount}, :size=>5, :class=>"text"
  = image_tag("refreshArrow.gif",:class=>"revert-icon", :style=>"display:none;",:title=>"Revert to default, #{field.default}")
EOS
end

然后您就有一个有效的Haml作用域,因此image_tab、form_tag_helpers等都可以工作。

2
class RailsRenderingContext
  def self.create(controller)
    view_context = ApplicationController.helpers
    class << view_context; include Rails.application.routes.url_helpers; end

    view_context.request = controller.request
    view_context.view_paths = controller.view_paths
    view_context.controller = controller

    view_context
  end
end

class MyController < ApplicationController
  def show
    # ...
    engine = Haml::Engine.new haml
    ctx = RailsRenderingContext.create(self)
    engine.render ctx 
  end
end

对我来说可以用。基于这个问题。


非常好的解决方案!如果您只想在邮件中使用link_to,则可以省略以view_context.开头的三行代码。这样甚至不需要控制器。 - Kalsan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接