1

给定一个应用了多个过滤器的Sequel 数据集,我如何创建一个删除或覆盖现有过滤器之一的新数据集?

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)。虽然在上述简单案例中很容易重新添加,但在我的实际案例中会导致代码重复。

4

2 回答 2

1

我想这不是他们的主要用例,您可能想要进行基准测试,但您可以使用绑定变量

# 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)

请注意,绑定变量仅在与calland一起使用时才会被识别prepare,因此您不能只使用,例如ds2.first

于 2013-11-08T21:46:42.150 回答
1

您可以将选择规则存储在哈希中并重用哈希:

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_exchangefilter_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!修改您的原始数据集命令!即使是 ads.dup.filter_exchange!也会改变你原来的选择。

filter_exchange您一起获得修改后的数据集。(到目前为止还没有经过很好的测试)。

于 2013-11-08T20:45:47.093 回答