从模型内部访问 ActionView 助手

发布于 2024-10-02 00:16:39 字数 1674 浏览 3 评论 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 时缺少一些内容。

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

I have a simple template system which calls a show_me method defined inside different classes of my model (kinda Widgets) when rendering a template. These widgets originally returned the html as a string. So in my erb I have somethink like this.

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

As the views of the widgets became more complex I start using partials to render them, calling the ActionView::Base render method from inside my widgets (please don't throw up yet :)

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

So, this works like a charm (really...) but when I want to use helpers inside the widget specific partial (eg. widgets/_weater_widget.html.erb) they don't work. for example. javascript_tag raises

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'

I think I'm missing something when I create the ActionView::Base.

Any thoughts how to solve this? Also any suggestion on the overall design is welcome too :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不一样的天空 2024-10-09 00:16:39

您也许可以调用视图助手来从模型中工作,但 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 技术在 widget 演示者之间共享演示逻辑,并且可以通过将您的信息与其演示分离来让 Rails(以及未来的开发人员)满意。

You may be able to get a call to a view helper to work from a model, but Rails will fight you every step of the way. Rails doesn't want you to do things like this.

Consider introducing a widget presenter class. It could live in app/helpers, like

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

That way you can use OO techniques to share presentation logic between widget presenters, and you can keep Rails happy (and future developers) by isolating your information from it's presentation.

獨角戲 2024-10-09 00:16:39

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

示例:

Model

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

  def settings
    ## something here
  end

  def data
    ## calculations here
  end
end

Helper

module WidgetHelper

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

end

View

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

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

Please for the love of all things MVC don't render view code from a model. :( There is always a better way to do it.

Example:

Model

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

  def settings
    ## something here
  end

  def data
    ## calculations here
  end
end

Helper

module WidgetHelper

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

end

View

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

Obviously that may not be the exact solution for your situation, but is just a guide to show you something that can be done to keep your code clean. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文