假设有一个产品控制器,您希望拥有索引(列表产品)操作。简单。现在假设您在项目中有管理和存储零件。两者都需要列出产品,但方式略有不同(例如,商店不应该有这个编辑产品链接)。它们也使用不同的布局。
到目前为止,我的想法是在不同的命名空间下有两个产品控制器 - app/controllers/admin/products_controller.rb
和app/controllers/store/products_controller.rb
- 每个产品控制器都有自己的视图和布局。但我怀疑这可能导致WET代码。或者引用其他控制器视图(这样可以避免模块化,因此应该避免)。
所以,实际的问题是:是否有更多干(或实际上是正确的)方法来实现上述目标?
我不确定这个标题是否真的反映了这个问题。但是,另一方面,如果是的话,我可能会回答这个问题。
修改 从3.1开始,Rails支持模板继承。
答案 0 :(得分:2)
如果你在admin部分和store部分之间显示产品的方式是不变的,除了管理链接(Create,Edit,Destroy),那么我认为为你的产品创建一个部分是最容易的。我假设你有办法告诉用户是否是管理员(我将只使用管理员?为简单起见)。在你的局部内你会做这样的事情......
<div class="product">
<div class="productheader">
<%=h product.title %>
</div>
<div class="productdescription>
<%=h product.description %>
</div>
<% if admin? %>
<div class="productadmin">
<%= link_to "Delete", destroy_product_url %>
<%= link_to "Edit", edit_product_url %>
</div>
<% end %>
</div>
请务必将此部分命名为_product.html.erb(下划线告诉rails该模板是部分的)。在应用程序的app / views目录中创建一个名为shared的文件夹,并将部分存储在那里。
要在其他视图中渲染此部分,只需调用render方法并传递partial参数即可。
单品:
<%= render(:partial => "shared/product", :object => @a_product) %>
多种产品:
<%= render(:partial => "shared/product", :collection => @products) %>
可以通过添加布局参数将布局应用于局部视图。部分布局必须以下划线为前缀,但存储在与控制器关联的app / views目录中。
<%= render(:partial => "shared/product", :object => @a_product, :layout => "somelayout" %>
答案 1 :(得分:1)
我采用的方法是为产品配备一个控制器,并为其添加代码,以检测用户所扮演的角色,并根据该角色有条件地设置视图数据。这包括实际模型数据和仅由视图使用的数据,以确定要显示的接口的哪些位。然后,视图本身包含一些少量代码,这些代码能够对基于角色的数据执行操作,并仅呈现与特定角色相关的那些位。有人可能会争辩说,这会在视图中注入一些小的业务逻辑,或者在控制器中注入一些显示逻辑 - 这些参数都有一定的效力。但是,我发现这更像是原则之间的平衡,我更喜欢DRY而不是MVC纯度。
答案 2 :(得分:0)
您正在描述模型 - 视图 - 控制器模式,其中模型视图和控制器可以正交变化(或者或多或少地正交变化,具体取决于其实现方式)。
基本上,你有一个允许编辑的视图和一个不允许编辑的视图。同样,根据实现,可编辑视图可能从不可编辑的视图派生。在任何一种情况下,控制器或某些更高级别的代码都会有条件地选择正确的视图。
答案 3 :(得分:0)
如果只有某种视图继承...那么可以将控制器子类化而无需提供其所有视图。好的是有patch。不好的是,它不能在很长一段时间内成为核心。
将它应用到我的rails 2.2后,我设法得到了原始问题的以下答案。
子类控制器
ProductController得到了双胞胎的祝福:
class Products::AdminController < ProductsController
layout 'admin'
before_filter :authenticate
end
和
class Products::StoreController < ProductsController
layout 'store'
before_filter :find_cart
end
这本身看起来很不错,因为它们每个都带有自己的初始化部分。
更改路线
map.resources :products, :controller => 'products/admin', :path_prefix => 'admin',
:name_prefix => 'admin_'
map.resources :products, :controller => 'products/store', :path_prefix => 'store',
:only => [:show, :index], :name_prefix => 'store_'
不是一条简单的路线,defo。但是,嘿,在这一点之后,一切都正常工作(假设你修复了路径助手)和ProductController视图和部分。
共享视图更改
每个子类控制器都有自己的index.html.erb版本。其他所有内容都在基类中共享。
谈谈共享模板中的路径助手。过去是什么
<% form_for @product ... %>
变为
<% form_for [controller_name, @product] ... %>
并且喜欢
<%= link_to products_path %>
变成
<%= link_to send("#{controller_name}_products_path") %>
我不知道这一切是否值得,但这是一种方式。任何人都知道为什么有计划很快将这个补丁包含在rails中?