ruby on rails -在这个控制器中有一个DRYer方法吗?



使用ROR 2.3.8.

下面是我的代码:

class CitiesController < ApplicationController  
  def show
    ...
  end
  def western
    @city = City.find(params[:id])
    @spots = Spot.paginate(
      :conditions => ["(city=? or state=?) and country=? and shop_type=?", "#{@city.name}", "#{@city.name}", @city.country, "Places"], 
      :page => params[:page], 
      :per_page => 20, 
      :order => 'rating_average DESC'
      )
  end
  def middle-east
    @city = City.find(params[:id])
    @spots = Spot.paginate(
      :conditions => ["(city=? or state=?) and country=? and shop_type=?", "#{@city.name}", "#{@city.name}", @city.country, "Food"], 
      :page => params[:page], 
      :per_page => 20, 
      :order => 'rating_average DESC'
      )
  end
  def asian
    @city = City.find(params[:id])
    @spots = Spot.paginate(
      :conditions => ["(city=? or state=?) and country=? and shop_type=?", "#{@city.name}", "#{@city.name}", @city.country, "Accommodation"], 
      :page => params[:page], 
      :per_page => 20, 
      :order => 'rating_average DESC'
      )
  end
end

我创建了western.html.erb, middle-east.html.erb, asian.html.erb_shops.html.erb

所以前三个基本上是空的,但产生_shops.html.erb,以便不让我重新编码视图布局。

是否有更好的方法来编写控制器?

谢谢!

在Rails 2.3中正确的处理方法。X是模型中的命名作用域。控制器中过多/重复的查询是代码异味的暗示。如果你不相信我,杰米斯·巴克会支持我的!http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model

在你的Spot模型中:

# app/models/spot.rb
named_scope :by_type, lambda { |city, type|
  {:conditions => ["(city=? or state=?) and country=? and shop_type=?", city.name, city.name, city.country, type] }
}

在你的城市控制器:

#app/contollers/cities_controller.rb
before_filter :fetch_city, :except => :show
def western
  @spots = paginate_spots("Places")
end
....
private
def fetch_city
  @city = City.find(params[:id])
end
def paginate_spots(type)
  Spot.by_type(@city,type).paginate(:page => params[:page], 
    :per_page => 20, 
    :order => 'rating_average DESC'
  )
end

这完成的是将大部分查询逻辑从控制器中移除。这是一件好事,因为它允许你根据城市找到地点,并在需要时输入其他控制器。分页可能是特定于您的单个控制器的,因此我倾向于将其排除在模型内的作用域之外。如果您想构建一个API,您可能会限制为50而不是20,并且希望通过不同的方法进行排序。

第一种方法:使用before_filterupd: it won't work for you(出于教育目的,我将把它留在这里)

class CitiesController < ApplicationController  
  before_filter :spots_and_city, :only => [:asian, :western, :middle-east]
  def show
    ...
  end
  def western
  end
  def middle-east
  end
  def asian
  end
  private
  def spots_and_city(type)
    @city = City.find(params[:id])
    @spots = Spot.paginate(
      :conditions => ["(city=? or state=?) and country=? and shop_type=?", "#{@city.name}", "#{@city.name}", @city.country, "Accommodation"], 
      :page => params[:page], 
      :per_page => 20, 
      :order => 'rating_average DESC'
      )
  end
end

第二种方法使用helper method: updated

class CitiesController < ApplicationController  
  helper_method :spots, :city
  def show
    ...
  end
  def western
    @city = city
    @spots = spots("Places")
  end
  def middle-east
    @city = city
    @spots = spots("Food")
  end
  def asian
    @city = city
    @spots = spots("Accommodation")
  end
  private
  def city
    city ||= City.find(params[:id])
  end
  def spots(type)
    spots ||= Spot.paginate(
      :conditions => ["(city=? or state=?) and country=? and shop_type=?", "#{@city.name}", "#{@city.name}", @city.country, type], 
      :page => params[:page], 
      :per_page => 20, 
      :order => 'rating_average DESC'
      )
  end
end

第三:使用Decent Exposure

http://railscasts.com/episodes/259-decent-exposure

在我看来,我更喜欢用helper_method来做这样的工作。

相关内容

最新更新