过滤结果导致Rails

时间:2012-08-10 07:29:41

标签: ruby-on-rails ruby ruby-on-rails-3

当用户使用索引操作时,我会显示一系列问题。我想过滤此列表,仅显示被拒绝的问题,仅附加图像的问题等。

你是怎么做到的?您是否只是在索引操作中添加代码,以检查请求参数哈希中是否有不同的命名参数,并使用它们构建查询。

myurl.com/questions?status=approved&only_images=yes

还是有更好的方法吗?

3 个答案:

答案 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过滤控制器中私有方法中来自视图的任何不需要的过滤器参数。