Ruby on rails 可以在Rails中有条件地链接作用域吗?
考虑以下代码:Ruby on rails 可以在Rails中有条件地链接作用域吗?,ruby-on-rails,Ruby On Rails,考虑以下代码: class Car scope :blue, -> { where(color: "blue") } scope :manual, -> { where(transmission: "manual") } scope :luxury, -> { where("price > ?", 80000) } end def get_cars(blue: false, manual: false, luxury: false) cars = Car
class Car
scope :blue, -> { where(color: "blue") }
scope :manual, -> { where(transmission: "manual") }
scope :luxury, -> { where("price > ?", 80000) }
end
def get_cars(blue: false, manual: false, luxury: false)
cars = Car.all
cars = cars.blue if blue
cars = cars.manual if manual
cars = cars.luxury if luxury
end
有没有一种方法可以有条件地链接这些范围,如车、蓝、手动、豪华等?也就是说,如果arg为true,则只有作用域?可以有条件地应用ActiveRecord作用域,如下所示:
scope :blue, -> { where(color: 'blue') if condition }
Task.blue(color == 'blue')
scope :color, ->(color) { where(color: color) if color.present? }
Car.color('blue') # returns blue cars
Car.color(nil) # returns all cars
Car.color(params[:color]) # returns either all cars or only cars of a specific color, depending on value of param[:color]
Car.color(params[:color]).transmission(params[:transmission]).price(params[:price])
其中,条件
是您定义的返回true或false的内容。如果条件返回true,则应用范围。如果条件为false,则忽略范围
您还可以将值传递到范围:
scope :blue, ->(condition) { where(color: 'blue') if condition }
所以,你可以这样做:
scope :blue, -> { where(color: 'blue') if condition }
Task.blue(color == 'blue')
scope :color, ->(color) { where(color: color) if color.present? }
Car.color('blue') # returns blue cars
Car.color(nil) # returns all cars
Car.color(params[:color]) # returns either all cars or only cars of a specific color, depending on value of param[:color]
Car.color(params[:color]).transmission(params[:transmission]).price(params[:price])
这与OP要求的类似。但是,你为什么要这么做
更好的方法是这样的:
scope :blue, -> { where(color: 'blue') if condition }
Task.blue(color == 'blue')
scope :color, ->(color) { where(color: color) if color.present? }
Car.color('blue') # returns blue cars
Car.color(nil) # returns all cars
Car.color(params[:color]) # returns either all cars or only cars of a specific color, depending on value of param[:color]
Car.color(params[:color]).transmission(params[:transmission]).price(params[:price])
可以这样称呼:
scope :blue, -> { where(color: 'blue') if condition }
Task.blue(color == 'blue')
scope :color, ->(color) { where(color: color) if color.present? }
Car.color('blue') # returns blue cars
Car.color(nil) # returns all cars
Car.color(params[:color]) # returns either all cars or only cars of a specific color, depending on value of param[:color]
Car.color(params[:color]).transmission(params[:transmission]).price(params[:price])
您的里程数可能会有所不同。您可以使用ruby 2.5中为其添加的新功能yield\u self() 在您的示例中:
class Car
scope :blue, -> { where(color: "blue") }
scope :manual, -> { where(transmission: "manual") }
scope :luxury, -> { where("price > ?", 80000) }
end
def get_cars(blue: false, manual: false, luxury: false)
cars = Car.all
.yield_self { |cars| blue ? cars.blue : cars }
.yield_self { |cars| manual ? cars.manual : cars }
.yield_self { |cars| luxury ? cars.luxury : cars }
end
你已经做的事情有什么问题吗?我想这应该行得通。我想在一行中创建一个查询,而不是调用每个函数并在每个步骤存储部分结果。你不是在存储部分结果,而是在一步一步地创建查询。在您尝试对需要结果的
cars
执行某些操作之前,不会命中数据库(即没有部分结果或其他结果)。