MVC Web 框架中不相关视图的优雅解决方案是什么?

发布于 2024-09-12 16:55:49 字数 1405 浏览 3 评论 0原文

我在 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 %>

(注意我已经忽略了不相关的产品视图)< /em>

并且菜单有一部分...

<% Category.each {|c| %>
   <%= render :partial => 'menu_node', :locals => { :category => c } %>
<% } %>

我遇到问题的行是视图中的“Category.each.do”。我在视图中获取数据,而不是使用在控制器中设置和绑定的变量。它很可能是生成菜单的更复杂的方法调用。

我考虑过的解决方案是:

- 知道如何获取各种数据的视图模型基类。但您最终可能会为网站的每个概念“部分”提供其中一个。
- 填充在每个方法顶部的局部变量(违反 DRY) -同样的事情,但是在 before_filter 调用中,

这些对我来说都不是很优雅。我忍不住看看这个问题,并认为每个视图(而不是屏幕)都有一个 MVP 演示者是一个更优雅的解决方案。

ASP.Net MVC 具有渲染操作(与 Rails render :action 不同),它确实解决了这个问题,但我不确定我对该解决方案的看法。

想法?解决方案建议?

添加注释: 到目前为止提供的答案都是很好的建议。它们适用于我给出的示例,其中菜单可能出现在每个布局中,并且显然是次要于产品数据的。

但是,如果明明没有二等公民怎么办?门户类型网站通常有多个不相关的小部件,其中每个小部件都很重要。

例如,如果此页面显示天气趋势,并带有温度、湿度和降水小部件(每个小部件都有不同的模型和视图类型),该怎么办?

I've had a problem with the following issue in Rails and ASP.Net MVC. Often there are multiple widgets of functionality on a page, yet one controller action is supposed to render the page. Let me illustrate:

Let's say I have a normal e-commerce site, and the menu is made of categories, while the page is to display an group of products.

For the products, let's say I have an action on a controller that looks something like:

def product_list
     @products = Products.find_by_category(:name => 'lawnmowers')
end

And I have a layout with something like

<div id="menu"><%= render :partial => 'menu' %></div>
<div id="content"><%= yield %></div>

The products have a view...

<%= render :partial => 'product', :collection => @products %>

(note I've ommited the product view as irrelevant)

And the menu has a partial...

<% Category.each {|c| %>
   <%= render :partial => 'menu_node', :locals => { :category => c } %>
<% } %>

The line I have a problem with is the "Category.each.do" in the view. I'm fetching data in the view, as opposed to using variables that were set and bound in the controller. And it could easily be a more complex method call that produces the menu.

The solutions I've considered are:

-A view model base class that knows how to get various pieces of data. But you could end up with one of these for each conceptual "section" of the site.
-a local variable that populates at the top of each method (violates DRY)
-the same thing, but in a before_filter call

None of these seem very elegant to me. I can't help but look at this problem and think that a MVP presenter per view (not screen) is a more elegant solution.

ASP.Net MVC has render action (different from rails render :action), which does address this, but I'm not sure what I think of that solution.

Thoughts? Solution suggestions?

Added Note:
The answers provided so far are good suggestions. And they apply to the example I gave, where a menu is likely present in every layout, and is clearly secondary to the product data.

However, what if there is clearly no second class citizen? Portal type sites commonly have multiple unrelated widgets, in which each is important.

For example, What if this page was displaying weather trends, with widgets for temperature, humidity, and precipitation (and each is a different model and view type).

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

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

发布评论

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

评论(2

甜`诱少女 2024-09-19 16:55:49

在 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 。

In rails we like to have a concept of thin-controllers, thick-models. So I think you're right to not want to have variables set in the controller.

Also, in order to enable a more-complex method later on, I recommend doing something like:

/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

That way in the future you could update Category.menu_nodes with a more complicated solution, based on the current user, if you need.

小糖芽 2024-09-19 16:55:49

如果我屠宰了红宝石(或误解了你的问题),请原谅我,但是

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

视图中

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

有什么问题?

Forgive me if I butcher the Ruby (or misunderstand your question), but what's wrong with

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

in the view

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

?

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