Каково элегантное решение для несвязанных представлений в веб-инфраструктурах MVC? - PullRequest
11 голосов
/ 02 августа 2010

У меня была проблема со следующей проблемой в Rails и 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 имеет действие рендера (отличное от рельсов рендеринга: действие), которое решает эту проблему, но я не уверен, что думаю об этом решении.

Мысли? Предложения решения?

Добавлено примечание: Ответы, представленные до сих пор, являются хорошими предложениями. И они применимы к приведенному мною примеру, где меню, скорее всего, присутствует в каждом макете и явно вторично данным продукта.

Однако, что, если явно нет второго сорта гражданина? Сайты типа портала обычно имеют несколько несвязанных виджетов, каждый из которых важен.

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

Ответы [ 2 ]

3 голосов
/ 02 августа 2010

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

Кроме того, чтобы позже включить более сложный метод, я рекомендую сделать что-то вроде:

/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 более сложным решением, основанным на текущем пользователе, если вам нужно.

1 голос
/ 02 августа 2010

Простите, если я убью Рубина (или неправильно пойму ваш вопрос), но что не так с

class section_helper
    def menu( section )
        // ...
        menuBuiltAbove
    end
end

в представлении

<%= section_helper.menu( 'section' ) %>

...