【问题标题】:Rails query doesnt work properlyRails 查询无法正常工作
【发布时间】:2014-02-11 13:26:51
【问题描述】:

我有一个带有过滤器的页面,但它不能正常工作,如果设置了所有过滤器,它就可以工作。 但是,如果未设置类别过滤器并且设置了其他两个过滤器,它将不起作用(它显示所有产品)。与之前一样,如果设置了类别并且再次设置了价格不是库存,则显示仅按类别过滤的内容。 我的模型是product.rb

def self.categorized(category=nil)
  return self.where("category_id LIKE ?",category ) if category
  self
end
def self.priced(price=nil)
  return self.where("price < 50") if price=="low"
  return self.where("price < 100 and price > 50") if price=="mid"
  return self.where("price > 100") if price=="high"
  self
end

def self.stocked(stock=nil)
  return self.where("stock > 0") if stock=="available"
  return self.where("stock = 0" ) if stock=="out"
  self
end
def self.catalog(params)
 page = params[:page]
 category = params[:category]
 stock = params[:stock]
 price = params[:price]
 self.stocked(stock).priced(price).categorized(category)
  .paginate(:page =>page).limit(9)
end

【问题讨论】:

  • 删除自我后尝试。在 self.price 和 self.stocked 内
  • @Thahakp 这会破坏链接,不会工作
  • 像这样... def self.price(price=nil) where("price 50") if price=="mid" where("price > 100") if price=="high" end
  • 如果你想链接你必须使用范围。
  • @Thahakp,不,您不必“必须”,这是另一种选择。 (我同意范围可能更像 Rails,但从技术上讲,OP 所做的还可以。)

标签: ruby-on-rails


【解决方案1】:

您的问题是self 并非您所期望的那样。由于这些是类级别的方法self 始终指的是“普通”类,而不是已经“聚合”了您使用的 where 子句的东西。您在这里想要返回的内容不会更改您到目前为止的链接查询。

def self.categorized(category=nil)
  return self.where("category_id LIKE ?",category ) if category
  scoped
end

应该工作

(更新了我的答案,不确定 Product.none 是否符合我的预期,并且仅适用于 Rails 4.0)。

【讨论】:

    【解决方案2】:

    为此使用范围,

    scope :priced, where("price < 50")
    scope :stocked, where("stock > 0")
    

    然后拨打Product.priced.stocked

    阅读更多关于作用域以及如何将变量传递给作用域here

    编辑:

    这将是您用于过滤的完整代码。请告诉我这是否有效。

      scope :categorized, (lambda do |category|
        where("category_id LIKE ?",category ) if category   
      end)
    
      scope :priced, (lambda do |price|
         where("price < 50") if price=="low"
         where("price < 100 and price > 50") if price=="mid"
         where("price > 100") if price=="high"
      end)
    
      scope :stocked, (lambda do |stock|
         where("stock > 0") if stock=="available"
         where("stock = 0" ) if stock=="out"
      end)
    
    def self.catalog(params)
     page = params[:page]
     category = params[:category]
     stock = params[:stock]
     price = params[:price]
     @products = Product.scoped
     @products.stocked(stock) if stock
     @products.priced(price) if price
     @products.categorized(category) if category
     @products.paginate(:page =>page).limit(9)    
    end
    

    【讨论】:

    • 是的,这行得通。尽管为了更好的 OOP 设计,您仍然应该在范围方法中使用 Null Relation。这样你就不必担心最后所有的if stock 和类似的事情,如果没有属性适用,只需返回 Product.none 并且你可以链接范围。当您这样做时,外界需要了解范围方法的工作原理。
    • 是的,这行得通。尽管为了更好的 OOP 设计,您仍然应该在范围方法中使用 Null Relation。这样你就不必担心所有那些if stock 和最后类似的事情,如果没有属性适用,只需返回 Product.none 并且你可以链接范围。当您这样做时,外界需要了解范围方法的工作原理。
    • 顺便说一句:我认为你必须这样做@products = @products.stocked(stock) if stock
    • 如果我们添加 Product.none if stock.nil?在库存范围内,如果库存 == nil,则得到空结果。下一行调用此结果的定价范围。定价范围内的 Where 子句将附加到空产品。那么结果总是空的。如果我错了,请纠正我。
    • 似乎我弄错了 ActiveRecord#none 到底是做什么的。我认为如果你使用scoped 作为返回值,这应该会产生预期的效果,它不会改变已经应用的范围,但仍然可以被链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多