Получить доступ к помощникам ActionView из Модели
У меня есть простая система шаблонов, которая вызывает 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 ответа
Пожалуйста, ради любви ко всем вещам, 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 %>
Очевидно, что это не может быть точным решением для вашей ситуации, но это просто руководство, чтобы показать вам, что можно сделать, чтобы сохранить ваш код в чистоте.:)
Возможно, вам удастся вызвать помощника вида для работы с моделью, но 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
Таким образом, вы можете использовать ОО-методы для обмена логикой представления между докладчиками виджетов, и вы можете порадовать Rails (и будущих разработчиков), изолируя вашу информацию от ее представления.