当用户使用索引操作时,我会显示一系列问题。我想过滤此列表,仅显示被拒绝的问题,仅附加图像的问题等。
你是怎么做到的?您是否只是在索引操作中添加代码,以检查请求参数哈希中是否有不同的命名参数,并使用它们构建查询。
myurl.com/questions?status=approved&only_images=yes
还是有更好的方法吗?
答案 0 :(得分:3)
您可以使用has_scope来优雅地执行此操作:
# Model
scope :status, proc {|status| where :status => status}
scope :only_images, ... # query to only include questions with images
# Controller
has_scope :status
has_scope :only_images, :type => boolean
def index
@questions = apply_scopes(Question).all
end
答案 1 :(得分:1)
为了保持控制器的薄度并避免使用意大利面条代码,您可以尝试使用以下方式:
控制器:
def index
@questions = Question.filter(params.slice(:status, :only_images, ...) # you still can chain with .order, .paginate, etc
end
型号:
def self.filter(options)
options.delete_if { |k, v| v.blank? }
return self.scoped if options.nil?
options.inject(self) do |scope, (key, value)|
return scope if value.blank?
case key
when "status" # direct map
scope.scoped(:conditions => {key => value})
when "only_images"
scope.scoped(:conditions => {key => value=="yes" ? true : false})
#just some examples
when "some_field_max"
scope.scoped(:conditions => ["some_field <= ?", value])
when "some_field_min"
scope.scoped(:conditions => ["some_field >= ?", value])
else # unknown key (do nothing. You might also raise an error)
scope
end
end
end
答案 2 :(得分:0)
所以,我认为有些地方你需要编码才能在这种情况下做得好;模型和控制器。
对于模型,您应该使用范围。
#Model
scope :rejected, lambda { where("accepted = false") }
scope :accepted lambda { where("accepted = true") }
scope :with_image # your query here
在控制器中,
def index
@questions = @questions.send(params[:search])
end
您可以从UI发送方法名称,并直接将其传递给模型中的范围。此外,您可以通过再次从UI传递.all案例来避免“if”条件。
但由于这直接暴露了要查看的Model代码,因此您应该使用before_filter过滤控制器中私有方法中来自视图的任何不需要的过滤器参数。