使用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_filter
。upd: 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
来做这样的工作。