如何有条件地通过范围内的标准

时间:2013-11-26 09:13:27

标签: ruby mongoid

我正在使用mongoid 3.15。 我有一个名为'Building'的模型,其中包含属性:name,province,district,street。我想创建一个范围(或类方法),例如'in'。它应该接受包含(或全部)'省','区'和'街道'之一的哈希标准 - 如果其中一个提供,则按其中一个属性进行搜索 - 如果提供了两个或更多个,那么它应该找到符合所有标准的建筑物

建筑模型

    class Building
      include Mongoid::Document
      store_in collection: 'buildings'

      field :name, type: String
      field :province, type: String
      field :district, type: String
      field :street, type: String

      #scope/class method to search by province/district/street
      def self.in(crit = {})
        #see the logic below
      end
    end

我试过2个解决方案,但没有一个有效:

      def self.in(crit = {})
        where(province: crit[:province]) if crit[:province]
        where(district: crit[:district]) if crit[:district]
        where(street: crit[:street]) if crit[:street]
      end

如果只提供'省'或'区'或'街道',但不是两个或全部,因为后来'哪里'胜利

      def self.in(crit = {})
        query = where(province: crit[:province])
        query = query.where(district: crit[:district]) if crit[:district]
        query = query.where(street: crit[:street]) if crit[:street]
      end

有了这个,你必须始终提供'省'

请帮助我使其工作或为我提供另一种解决方案

谢谢你,对不起我的英文

将drinor的答案与使用范围样式相结合,问题解决了:

    scope :in, -> (crit = {}) {
        conditions = []
        conditions.push { :province => crit[:province] } if crit[:province]
        conditions.push { :district => crit[:district] } if crit[:district]
        conditions.push { :street => crit[:street] } if crit[:street]
        where( "$and" => conditions ) unless conditions.empty?
    }

2 个答案:

答案 0 :(得分:0)

试一试:

def self.in(crit = {})
    conditions = []
    conditions.push { :province => crit[:province] } if crit[:province]
    conditions.push { :district => crit[:district] } if crit[:district]
    conditions.push { :street => crit[:street] } if crit[:street]
    where( "$and" => conditions ) unless conditions.empty?
end  

答案 1 :(得分:0)

您可以将条件拆分为范围并在每个范围内使用条件。

scope :province, -> province { where(province: province) if province.present? }
scope :district, -> district { where(province: district) if district.present? }
scope :strict, -> street { where(province: street) if street.present? }

查看Active Record scopes vs class methods文章和“范围始终可链接”部分了解更多详情。