0

我有一个简单的模板系统,它在渲染模板时调用show_me在我的模型的不同类(有点小部件)中定义的方法。这些小部件最初将 html 作为字符串返回。所以在我的erb中,我有这样的想法。

<% @template.widgets.each do |widget| %>
   <%= widget.show_me %>    
<% end %>

随着小部件的视图变得更加复杂,我开始使用局部渲染它​​们,ActionView::Base从我的小部件内部调用渲染方法(请不要扔掉:)

def show_me
      # ... specific calculations and other magic.
    ActionView::Base.new(MyApp::Application.config.view_path).render(:partial => "widgets/weather_widget", :locals => {:data => data, :settings => settings})  
end

所以,这就像一个魅力(真的......)但是当我想在小部件特定的部分(例如widgets/_weater_widget.html.erb)中使用帮助器时,它们不起作用。例如。javascript_tag提高

can't convert nil into String
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:790:in `join'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:790:in `rails_asset_id'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:813:in `rewrite_asset_path'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:742:in `compute_public_path'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:256:in `javascript_path'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:822:in `javascript_src_tag'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:362:in `block in javascript_include_tag'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:362:in `collect'
actionpack (3.0.0) lib/action_view/helpers/asset_tag_helper.rb:362:in `javascript_include_tag'

我想我在创建 ActionView::Base 时遗漏了一些东西。

任何想法如何解决这个问题?也欢迎对整体设计提出任何建议:)

4

2 回答 2

3

您可能可以调用视图助手来从模型中工作,但 Rails 会在每一步都与您抗衡。Rails 不希望你做这样的事情。

考虑引入一个小部件演示者类。它可以app/helpers,像这样生活

module WidgetHelper
  class WidgetPresenter < Struct.new(:widget)
    def show_me
      render(:partial => "widgets/#{widget.class}/show", :locals => {:widget => widget })
    end
  end

  def show_widgets(template)
    @template.widgets.map do |widget|
        WidgetPresenter.new(widget).show_me
    end.join
  end
end

这样,您可以使用 OO 技术在小部件演示者之间共享演示逻辑,并且可以通过将您的信息与演示文稿隔离开来让 Rails(以及未来的开发人员)满意。

于 2010-11-08T21:47:31.830 回答
-1

请出于对所有事物的热爱,MVC 不要从模型中渲染视图代码。:( 总是有更好的方法来做到这一点。

例子:

模型

class Widget < ActiveRecord::Base
  def name
    "weather_widget"
  end

  def settings
    ## something here
  end

  def data
    ## calculations here
  end
end

帮手

module WidgetHelper

  def render_widget(widget)
    render(:partial => "widgets/_#{widget.name}", :locals => {:data => widget.data, :settings => widget.settings})
  end

end

看法

<% @template.widgets.each do |widget| %>
  <%= render_widget(widget) %>    
<% end %>

显然,这可能不是适合您的情况的确切解决方案,而只是向您展示可以采取哪些措施来保持代码清洁的指南。:)

于 2010-11-08T21:38:11.960 回答