Class: Torque::PostgreSQL::AuxiliaryStatement

Inherits:
Object
  • Object
show all
Defined in:
lib/torque/postgresql/auxiliary_statement.rb,
lib/torque/postgresql/auxiliary_statement/settings.rb,
lib/torque/postgresql/auxiliary_statement/recursive.rb

Direct Known Subclasses

Recursive

Defined Under Namespace

Classes: Recursive, Settings

Constant Summary collapse

TABLE_COLUMN_AS_STRING =
/\A(?:"?(\w+)"?\.)?"?(\w+)"?\z/.freeze

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ AuxiliaryStatement

Start a new auxiliary statement giving extra options



114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 114

def initialize(*, **options)
  args_key = Torque::PostgreSQL.config.auxiliary_statement.send_arguments_key

  @join = options.fetch(:join, {})
  @args = options.fetch(args_key, {})
  @where = options.fetch(:where, {})
  @select = options.fetch(:select, {})
  @join_type = options[:join_type]

  @bound_attributes = []
  @join_sources = []
end

Class Attribute Details

.configObject (readonly)

Returns the value of attribute config.



12
13
14
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 12

def config
  @config
end

.table_nameObject (readonly)

Returns the value of attribute table_name.



12
13
14
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 12

def table_name
  @table_name
end

Instance Attribute Details

#bound_attributesObject (readonly)

Returns the value of attribute bound_attributes.



111
112
113
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 111

def bound_attributes
  @bound_attributes
end

#join_sourcesObject (readonly)

Returns the value of attribute join_sources.



111
112
113
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 111

def join_sources
  @join_sources
end

Class Method Details

.arel_query?(obj) ⇒ Boolean

Identify if the query set may be used as arel

Returns:

  • (Boolean)


56
57
58
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 56

def arel_query?(obj)
  !obj.nil? && obj.is_a?(::Arel::SelectManager)
end

.build(statement, base, bound_attributes = [], join_sources = [], **options) ⇒ Object

Fast access to statement build



40
41
42
43
44
45
46
47
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 40

def build(statement, base, bound_attributes = [], join_sources = [], **options)
  klass = instantiate(statement, base, **options)
  result = klass.build(base)

  bound_attributes.concat(klass.bound_attributes)
  join_sources.concat(klass.join_sources)
  result
end

.configurator(config) ⇒ Object

Set a configuration block or static hash



78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 78

def configurator(config)
  if config.is_a?(Hash)
    # Map the aliases
    config[:attributes] = config.delete(:select) if config.key?(:select)

    # Create the struct that mocks a configuration result
    config = OpenStruct.new(config)
    table_name = config[:query]&.klass&.name&.underscore
    instance_variable_set(:@table_name, table_name)
  end

  @config = config
end

.configure(base, instance) ⇒ Object

Run a configuration block or get the static configuration



93
94
95
96
97
98
99
100
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 93

def configure(base, instance)
  return @config unless @config.respond_to?(:call)

  recursive = self < AuxiliaryStatement::Recursive
  settings = Settings.new(base, instance, recursive)
  settings.instance_exec(settings, &@config)
  settings
end

.create(table_or_settings, &block) ⇒ Object

A way to create auxiliary statements outside of models configurations, being able to use on extensions



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 62

def create(table_or_settings, &block)
  klass = Class.new(self)

  if block_given?
    klass.instance_variable_set(:@table_name, table_or_settings)
    klass.configurator(block)
  elsif relation_query?(table_or_settings)
    klass.configurator(query: table_or_settings)
  else
    klass.configurator(table_or_settings)
  end

  klass
end

.instantiate(statement, base, **options) ⇒ Object

Create a new instance of an auxiliary statement

Raises:

  • (ArgumentError)


25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 25

def instantiate(statement, base, **options)
  klass = while base < ActiveRecord::Base
    list = base.auxiliary_statements_list
    break list[statement] if list.present? && list.key?(statement)

    base = base.superclass
  end

  return klass.new(**options) unless klass.nil?
  raise ArgumentError, <<-MSG.squish
    There's no '#{statement}' auxiliary statement defined for #{base.class.name}.
  MSG
end

.lookup(name, base) ⇒ Object

Find or create the class that will handle statement



15
16
17
18
19
20
21
22
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 15

def lookup(name, base)
  const = name.to_s.camelize << '_' << self.name.demodulize
  return base.const_get(const, false) if base.const_defined?(const, false)

  base.const_set(const, Class.new(self)).tap do |klass|
    klass.instance_variable_set(:@table_name, name.to_s)
  end
end

.relation_query?(obj) ⇒ Boolean

Identify if the query set may be used as a relation

Returns:

  • (Boolean)


50
51
52
53
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 50

def relation_query?(obj)
  !obj.nil? && obj.respond_to?(:ancestors) && \
    obj.ancestors.include?(ActiveRecord::Base)
end

.tableObject

Get the arel version of the statement table



103
104
105
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 103

def table
  @table ||= ::Arel::Table.new(table_name)
end

Instance Method Details

#build(base) ⇒ Object

Build the statement on the given arel and return the WITH statement



128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/torque/postgresql/auxiliary_statement.rb', line 128

def build(base)
  @bound_attributes.clear
  @join_sources.clear

  # Prepare all the data for the statement
  prepare(base, configure(base, self))

  # Add the join condition to the list
  @join_sources << build_join(base)

  # Return the statement with its dependencies
  [@dependencies, ::Arel::Nodes::As.new(table, build_query(base))]
end