class ToWa::Builder

Public Class Methods

like(v) click to toggle source

rubocop:enable Metrics/ParameterLists

# File lib/to_wa/builder.rb, line 28
def self.like(v)
  sanitize_sql_like(v)
end
new( restricted:, ex:, arel_table:, permitted_columns: Set.new, permitted_operators: Set.new, permitted_specified_columns: {} ) click to toggle source

rubocop:disable Metrics/ParameterLists

# File lib/to_wa/builder.rb, line 11
def initialize(
  restricted:,
  ex:,
  arel_table:,
  permitted_columns: Set.new,
  permitted_operators: Set.new,
  permitted_specified_columns: {}
)
  @restricted = restricted
  @arel_table = arel_table
  @initial_ex = ex.is_a?(String) ? JSON.parse(ex) : ex
  @permitted_columns = permitted_columns
  @permitted_operators = permitted_operators
  @permitted_specified_columns = permitted_specified_columns
end

Public Instance Methods

execute!() click to toggle source
# File lib/to_wa/builder.rb, line 32
def execute!
  decide(@initial_ex)
end

Private Instance Methods

add_comparison(op, left, right) click to toggle source
# File lib/to_wa/builder.rb, line 74
def add_comparison(op, left, right)
  normalize_value(left) { normalize_left_table(left) }.send(op, normalize_right(op, right))
end
add_logic(op, exes) click to toggle source
# File lib/to_wa/builder.rb, line 128
def add_logic(op, exes)
  logic = exes[1..-1].inject(decide(exes.first)) { |a, ex| a.send(op, decide(ex)) }
  Arel::Nodes::Grouping.new(logic)
end
all_specified_columns_allowed?() click to toggle source
# File lib/to_wa/builder.rb, line 103
def all_specified_columns_allowed?
  @permitted_specified_columns == ::ToWa::AllSpecifiedColumnsAllowance
end
between_to_gteq_and_lteq(left, right) click to toggle source
# File lib/to_wa/builder.rb, line 78
def between_to_gteq_and_lteq(left, right)
  decide({
    'and' => [
      { '>=' => [left, right.first] },
      { '<=' => [left, right.second] },
    ],
  })
end
decide(ex) click to toggle source
# File lib/to_wa/builder.rb, line 52
def decide(ex)
  op = detect_op!(ex.k)
  lr_or_exes = ex.v

  case op
  when 'not'
    decide(lr_or_exes.first).not
  when 'and', 'or'
    add_logic(op, lr_or_exes)
  when 'between'
    between_to_gteq_and_lteq(*lr_or_exes)
  else
    add_comparison(op, *lr_or_exes)
  end
end
detect_op!(op) click to toggle source
# File lib/to_wa/builder.rb, line 68
def detect_op!(op)
  sop = op.to_s
  raise ::ToWa::DeniedOperator, sop unless permitted_operators?(sop)
  ::ToWa::Core::OPERATORS[sop]
end
normalize_left_table(left) click to toggle source
# File lib/to_wa/builder.rb, line 87
def normalize_left_table(left)
  raise ::ToWa::DeniedColumn, left unless permitted_columns?(left)
  @arel_table[left]
end
normalize_right(op, right) click to toggle source
# File lib/to_wa/builder.rb, line 120
def normalize_right(op, right)
  if op == 'matches'
    "%#{ToWa::Builder.like(right)}%"
  else
    normalize_value(right)
  end
end
normalize_value(o, &block) click to toggle source
# File lib/to_wa/builder.rb, line 92
def normalize_value(o, &block)
  case
  when o.is_a?(Hash) && o.k.to_s == 'col'
    specify_columns(*o.v.map(&:to_s))
  when block_given?
    block&.call
  else
    o
  end
end
permitted_columns?(v) click to toggle source
# File lib/to_wa/builder.rb, line 42
def permitted_columns?(v)
  return true unless restricted?
  @permitted_columns.include?(v)
end
permitted_operators?(v) click to toggle source
# File lib/to_wa/builder.rb, line 47
def permitted_operators?(v)
  return true unless restricted?
  @permitted_operators.include?(v)
end
permitted_specified_columns?(table, column) click to toggle source
# File lib/to_wa/builder.rb, line 107
def permitted_specified_columns?(table, column)
  return true unless restricted?
  return true if all_specified_columns_allowed?

  @permitted_specified_columns[table]&.include?(column)
end
restricted?() click to toggle source
# File lib/to_wa/builder.rb, line 38
def restricted?
  @restricted
end
specify_columns(table, column) click to toggle source
# File lib/to_wa/builder.rb, line 114
def specify_columns(table, column)
  raise ::ToWa::DeniedColumn, [table, column] unless permitted_specified_columns?(table, column)

  Arel::Table.new(table)[column]
end