我有一个数组,我想用OR
子句调用范围:
cars = ['bmw', 'audi', 'toyota']
class Car < AR
scope :from_bmw, -> { where(type: 'bmw') }
scope :from_audi, -> { where(type: 'audi') }
scope :from_toyota, -> { where(type: 'toyota') }
end
我想实现这样的事情:
Car.from_bmw.or(Car.from_audi).or(Car.from_toyota)
我的cars
数组可以更改;如果:cars = ['toyota', 'audi']
,我的方法应该产生:
Car.from_toyota.or(Car.from_audi)
我有如下内容:
def generate(cars)
scopes = cars.map {|f| "from_#{f} "}
scopes.each do |s|
# HOW TO I ITERATE OVER HERE AND CALL EACH SCOPE???
end
end
我不想将类型作为参数传递给范围,这背后是有原因的。
def generate(cars)
return Car.none if cars.blank?
scopes = cars.map {|f| "from_#{f} "}
scope = Car.send(scopes.shift)
scopes.each do |s|
scope = scope.or(Car.send(s))
end
scope
end
假设给定的数组只包含有效的type
值,你可以简单地这样做:
class Car
scope :by_type, -> (type) { where(type: type) }
end
types = ['bmw', 'audi', 'toyota']
Car.by_type(types) # => It'll generate a query using IN: SELECT * FROM cars WHERE type IN ('bmw', 'audi', 'toyota')
如果出于任何原因不想将数组作为参数传递给范围,则可以创建一个哈希,将数组值映射到有效的by_type
参数。
VALID_CAR_TYPES = { volkswagen: ['vw', 'volkswagen'], bmw: ['bmw'], ... }
def sanitize_car_types(types)
types.map do |type|
VALID_CAR_TYPES.find { |k, v| v.include?(type) }.first
end.compact
end
Car.by_type(sanitize_car_types(types))