У меня была проблема со следующей проблемой в направляющих и ASP.NET MVC. Часто существует несколько виджетов функциональности на странице, все же одно действие контроллера, как предполагается, представляет страницу. Позвольте мне проиллюстрировать:
Скажем, у меня есть нормальный сайт электронной коммерции, и меню сделано из категорий, в то время как страница должна отобразить группу продуктов.
Для продуктов скажем, у меня есть действие с контроллером, который выглядит что-то как:
def product_list
@products = Products.find_by_category(:name => 'lawnmowers')
end
И у меня есть расположение с чем-то как
<div id="menu"><%= render :partial => 'menu' %></div>
<div id="content"><%= yield %></div>
Продукты имеют представление...
<%= render :partial => 'product', :collection => @products %>
(обратите внимание, что я опустил обзор продукта как не важный),
И меню имеет частичное...
<% Category.each {|c| %>
<%= render :partial => 'menu_node', :locals => { :category => c } %>
<% } %>
Строка, с которой у меня есть проблема, является "Category.each.do" в представлении. Я выбираю данные в представлении, в противоположность использованию переменных, которые были установлены и связаны в контроллере. И это мог легко быть более сложный вызов метода, который производит меню.
Решения, которые я рассмотрел:
- Базовый класс модели представления, который знает, как получить различные части данных. Но Вы могли закончить с одним из них для каждого концептуального "раздела" сайта.
- локальная переменная, которая заполняет наверху каждого метода (нарушает DRY) - то же самое, но в вызове before_filter
Ни один из них не кажется очень изящным мне. Я не могу не посмотреть на эту проблему и думать, что предъявитель MVP на представление (не экранируют) является более изящным решением.
ASP.NET MVC имеет действие рендеринга (отличающийся от рендеринга направляющих: действие), который действительно обращается к этому, но я не уверен, что я думаю о том решении.
Мысли? Предложения решения?
Добавленное Примечание: ответы, предоставленные до сих пор, являются хорошими предложениями. И они относятся к примеру, который я дал, где меню, вероятно, присутствует в каждом расположении и явно вторично к данным продукта.
Однако, что, если нет ясно никакого гражданина второго класса? Портала сайты типа обычно имеют несколько несвязанных виджетов, в которых каждый важен.
Например, Что, если эта страница отображала погодные тенденции, с виджетами для температуры, влажности и осадков (и каждый - различная модель и тип представления).
В rails нам нравится концепция тонких контроллеров, толстых моделей. Поэтому я думаю, что вы правы, не желая иметь переменные, установленные в контроллере.
Также, для того, чтобы позже можно было использовать более сложный метод, я рекомендую сделать что-то вроде:
/app/controllers/application_controller.rb
before_filter :add_menu_nodes
def add_menu_nodes
@menu_nodes = Category.menu_nodes(current_user)
end
/app/views/layouts/application.html.erb
<%= render :partial=>:menu, :locals=>{:categories=>@menu_nodes} %>
/app/models/category.rb
def self.menu_nodes(current_user)
Category.all.order(:name)
end
Таким образом, в будущем вы сможете обновить Category.menu_nodes более сложным решением, основанным на текущем пользователе, если вам это понадобится.
Простите меня, если я нарушаю Ruby (или неправильно понял ваш вопрос), но что не так с
class section_helper
def menu( section )
// ...
menuBuiltAbove
end
end
в представлении
<%= section_helper.menu( 'section' ) %>
?