2013-11-08 4 views
1

Учитывая, что Sequel Dataset имеет несколько фильтров, как я могу создать новый набор данных, который удаляет или переопределяет один из существующих фильтров?Удалить часть фильтра набора данных

ds1 = DB[:x].filter(a:1, b:2) 
#=> <Sequel::Dataset: "SELECT * FROM x WHERE ((a = 1) AND (b = 2))"> 

ds2 = ds1.filter(a:42) # I want to CHANGE a, not add another 
#=> <Sequel::Dataset: "SELECT * FROM x WHERE ((a = 1) AND (b = 2) AND (a = 42))"> 

Sequel::Dataset#unfiltered метод удаляет все фильтры (например, она удаляет b=2). Хотя это было бы легко повторно добавить в вышеуказанный простой случай, это приведет к дублированию кода в моем реальном случае.

ответ

1

Вы можете хранить правила отбора в Hash и повторно использовать хэш:

require 'sequel' 

DB = Sequel.sqlite 

selection = { a: 1, b: 2 } 
ds1 = DB[:x].where(selection) 

selection[:a] = 5 #change data 
ds2a = ds1.unfiltered.filter(selection) # change selection 
ds2b = DB[:x].where(selection) #Alternative usage 

puts ds1.sql #SELECT * FROM `x` WHERE ((`a` = 1) AND (`b` = 2)) 
puts ds2a.sql #SELECT * FROM `x` WHERE ((`a` = 5) AND (`b` = 2)) 
puts ds2b.sql #SELECT * FROM `x` WHERE ((`a` = 5) AND (`b` = 2)) 

Я нашел возможность изменения набора данных с новыми методами filter_exchange и filter_exchange!.

require 'sequel' 
DB = Sequel.sqlite 

module Sequel 
    class Dataset 
    def filter_exchange!(filter) 
     filter.each{|key, value| 
     opts[:where].args.each{|arg| 
      if arg.args.first == key 
      arg.args.pop 
      arg.args << value 
      end 
     } 
     } 
     self 
    end 
    def filter_exchange(filter) 
     sel = self.unfiltered 
     filter.each{|key, value| 
     opts[:where].args.each{|arg| 
      if arg.args.first == key 
      sel = sel.filter(key => value) 
      else 
      sel = sel.filter(arg) 
      end 
     } 
     } 
     sel 
    end 
    end 
end 

ds1 = DB[:x].filter(a:1, b:2) 
puts ds1.sql      #SELECT * FROM `x` WHERE ((`a` = 1) AND (`b` = 2)) 
puts ds1.filter_exchange(a: 7).sql #SELECT * FROM `x` WHERE ((`a` = 7) AND (`b` = 2) 
puts ds1.sql      #SELECT * FROM `x` WHERE ((`a` = 1) AND (`b` = 2) 
puts ds1.filter_exchange!(a: 7).sql#SELECT * FROM `x` WHERE ((`a` = 7) AND (`b` = 2) 
puts ds1.sql      #SELECT * FROM `x` WHERE ((`a` = 7) AND (`b` = 2) 

filter_exchange! изменяет исходную команду набора данных! Даже ds.dup.filter_exchange! изменит ваш первоначальный выбор.

С filter_exchange вы получаете модифицированный набор данных. (Не очень хорошо проверены до сих пор).

1

Я думаю, его не их основной случай использования, и вы, вероятно, хотите бенчмарка, но вы можете использовать bound variables

# initial args 
ds1 = DB[:x].filter(a: :$a, b: :$b).bind(a: 1, b: 2) 
ds1.call(:first) # or :select, :update, et al. 

# then later 
ds2 = ds1.bind(a: 42) 
ds2.call(:first) # uses a = 42 and b = 2 

# or pass the args directly into call() 
ds2.call(:first, a: 42) 

Обратите внимание, что связанные переменные распознаются только при использовании call и prepare, так что вы можете Просто используйте, например ds2.first

Смежные вопросы