干燥原则。这太干了吗?

时间:2014-08-15 23:08:36

标签: ruby-on-rails ruby-on-rails-4 dry

遵循DRY原则并尽可能不重复我的代码,从而重用控制器操作和视图。

我在主页上使用了index.html.erb视图,您可以在此处看到http://frnsh.herokuapp.com/

然后重复使用此视图仅显示某个用户/供应商的列表 http://frnsh.herokuapp.com/vendors/2/listings

这很棒,因为我保持DRY并重复使用index.html.erb

但是,当您点击链接并前往http://frnsh.herokuapp.com/vendors/2/listings

时,我想显示该用户/供应商的简历以及最终的他们的徽标

这是可能的还是我应该真的创建了vendor.html.erb页面?如果可以保持DRY,我将如何自定义index.html.erb视图?

我的index.html.erb如下:

<div class="center">
 <div class="row">
   <% @listings.each do |listing| %>
  <div class="col-md-3">
  <div class="thumbnail">
    <%= link_to image_tag(listing.image.url), listing %>

  <div class="caption">
    <h3><%= listing.name %></h3>
    <p><%= link_to listing.user.name, vendor_listings_path(:vendor_id => listing.user.to_param) %></p>
    <p><%= number_to_currency(listing.price, :unit => "£") %></p>
    <p><%= listing.user.bio %></p>
  </div>
 </div>

 </div>

  <% end %>
</div>
</div>

如果需要,我的控制器也在下面:

class ListingsController < ApplicationController
 before_action :set_listing, only: [:show, :edit, :update, :destroy]
 before_filter :authenticate_user!, only: [:seller, :new, :create, :edit, :update, :destroy]
 before_filter :check_user, only: [:edit, :update, :destroy]
 before_filter :set_vendor, only: [:index]

def seller
  @listings = Listing.where(user: current_user).order("created_at DESC")
end

def index
 @listings  = @vendor.present? ? @vendor.listings : Listing.all
 @listings  = @listings.order("created_at DESC")
end

def show
end

def new
 @listing = Listing.new
end


 def edit
 end


 def create
   @listing = Listing.new(listing_params)
   @listing.user_id = current_user.id

 respond_to do |format|
  if @listing.save
    format.html { redirect_to @listing, notice: 'Listing was successfully created.' }
    format.json { render :show, status: :created, location: @listing }
  else
    format.html { render :new }
    format.json { render json: @listing.errors, status: :unprocessable_entity }
     end
   end
 end


 def update
   respond_to do |format|
  if @listing.update(listing_params)
    format.html { redirect_to @listing, notice: 'Listing was successfully updated.' }
    format.json { render :show, status: :ok, location: @listing }
  else
    format.html { render :edit }
    format.json { render json: @listing.errors, status: :unprocessable_entity }
  end
 end
end

def destroy
 @listing.destroy
  respond_to do |format|
  format.html { redirect_to listings_url, notice: 'Listing was successfully destroyed.' }
  format.json { head :no_content }
 end
end

2 个答案:

答案 0 :(得分:3)

我认为您is it too DRY?的问题是确实 is it right?


<强>结构

我写这个的原因是因为如果你看一下你创建的内容 - 每次调用你想要使用它的相应控制器动作时,你需要调用index部分。

这很重要,因为当你有一个应用程序时,至少从开发的角度来看,你需要确保你有一个直观的&em;流程。可扩展性。您使用partial运行的 risk 是每次调用时都必须保持相同的结构/接口

虽然不是问题,但每次创建新动作时都会变得非常严格 - 我认为这是您问题的核心方面(当您不知道如何为{{1}添加不同的样式选项时对象)

-

<强>物件

我一直在写这么多,但我认为它也适合你 - Rails是object orientated 。这意味着如果你想创建一个部分,你可以更好地适应你通常使用你的控制器/动作视图;将部分应用于特定的对象

listings

虽然是一个非常简化的演示,但我试图给你的是,如果你break up your partials to display objects,你将能够制作更多modular流< / p>

我认为您当前遇到的问题是您将#app/views/shared/_listing.html.erb #-> partial <%= link_to listing.name, listing %> #app/views/application/index.html.erb #-> root path <%= render "shared/listing", collection: @listings, as: "listing" %> #app/views/listings/index.html.erb <%= render "shared/listing", collection: @listings, as: "listing" %> #app/views/listings/show.html.erb <%= render "shared/listing", object: @listing %> 视为布局的一部分,因此会遇到一些antipatterns。实际上,您应该使用它来显示特定的对象,然后您可以围绕布局进行定制

答案 1 :(得分:1)

它不太干。实际上,您可以通过将@listings.each块中的所有内容移动到列表部分然后呈现该部分来进一步干掉它。 Rails提供了一个简写语法,render @listings将为你循环收集。

根据您的ListingsController代码,我将假设&#34; /&#34; (主页)URL和&#34; / vendors / 2 / listing&#34; URL既可以路由到列表#index action,也可以显示listing / index.html.erb。这意味着您尝试解决的问题是,如何根据供应商是否通过来显示listing / index.html.erb中的供应商信息。为此,请创建供应商部分,其中包含供应商存在时要显示的供应商信息。然后使用<%= render @vendor %>渲染供应商。如果缺少@vendorrender将返回nil并且不会显示任何内容,否则将显示部分内容。

Rails指南非常适合有关部分内容的更多信息:http://guides.rubyonrails.org/layouts_and_rendering.html