代码之家  ›  专栏  ›  技术社区  ›  Mauricio

从模型内部访问ActionView帮助程序

  •  0
  • Mauricio  · 技术社区  · 14 年前

    我有一个简单的模板系统,它调用 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时缺少了一些东西。

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

    2 回复  |  直到 14 年前
        1
  •  -1
  •   jenjenut233    14 年前

    出于对所有事物的热爱,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 %>
    

    显然,这可能不是解决您的情况的确切方法,但只是一个指南,向您展示可以做些什么来保持代码的整洁。:)

        2
  •  3
  •   Brian Dunn    14 年前

    您可能能够从模型中得到对视图助手的调用,但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(以及未来的开发人员)感到高兴。

    推荐文章