Module: ScopeHunter::Canonicalizer

Extended by:
Canonicalizer
Included in:
Canonicalizer
Defined in:
lib/scope_hunter/canonicalizer.rb

Instance Method Summary collapse

Instance Method Details

#normalize_hash(obj) ⇒ Object



38
39
40
41
# File 'lib/scope_hunter/canonicalizer.rb', line 38

def normalize_hash(obj)
  h = obj.is_a?(Hash) ? obj : {}
  h.transform_keys { |k| k.to_s }.transform_values { |_| :"?" }
end

#normalize_list(args) ⇒ Object



43
44
45
# File 'lib/scope_hunter/canonicalizer.rb', line 43

def normalize_list(args)
  Array(args).flatten.compact.map(&:to_s)
end

#normalize_order(args) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
# File 'lib/scope_hunter/canonicalizer.rb', line 47

def normalize_order(args)
  first = args.first
  case first
  when Hash
    first.map { |k, v| [k.to_s, v&.to_s] }
  when Symbol, String
    [[first.to_s, "asc"]]
  else
    []
  end
end

#signature(chain, model: nil) ⇒ Object

chain: array of msg:, args: output: stable signature string



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/scope_hunter/canonicalizer.rb', line 9

def signature(chain, model: nil)
  state = { model: model, where: {}, where_not: {}, joins: [], order: [] }

  chain.each do |step|
    state[:model] ||= step[:recv] if step[:recv].is_a?(String)

    case step[:msg]
    when :where, :rewhere
      state[:where].merge!(normalize_hash(step[:args].first))
    when :where_not
      state[:where_not].merge!(normalize_hash(step[:args].first))
    when :joins
      state[:joins] |= normalize_list(step[:args])
      state[:joins].sort!
    when :order
      state[:order] += normalize_order(step[:args])
    end
  end

  w  = state[:where].sort_by(&:first).map { |k, _| "#{k}:?" }.join(",")
  wn = state[:where_not].sort_by(&:first).map { |k, _| "#{k}:?" }.join(",")
  j  = state[:joins].join(",")
  o  = state[:order].map { |(c, d)| "(#{c},#{d || "asc"})" }.join(",")

  sig = "M=#{state[:model]}|W={#{w}}|J=[#{j}]|O=[#{o}]"
  sig += "|WN={#{wn}}" unless wn.empty?
  sig
end