получить доступ к помощникам ActionView из Модели - PullRequest
0 голосов
/ 08 ноября 2010

У меня есть простая система шаблонов, которая вызывает метод show_me, определенный в различных классах моей модели (вроде виджетов) при рендеринге шаблона. Эти виджеты изначально возвращали HTML в виде строки. Так что в моем эрбе есть нечто подобное.

<% @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 ]

3 голосов
/ 09 ноября 2010

Возможно, вам удастся получить вызов помощника вида для работы с моделью, но Rails будет сражаться с вами на каждом этапе пути.Rails не хочет, чтобы вы делали подобные вещи.

Подумайте о введении класса Presenter .Он может жить в 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

Таким образом, вы можете использовать ОО-методы для обмена логикой представления между докладчиками виджетов, и вы можете поддерживать Rails счастливым (и будущими разработчиками), изолируя вашу информацию от ее презентации.

0 голосов
/ 09 ноября 2010

Пожалуйста, ради всего святого, 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 %>

Очевидно, что это не может быть точным решением для вашей ситуации, но это просто руководство, чтобы показать вам, что можно сделать, чтобы сохранить ваш код в чистоте.:)

...