class AtomicJson::QueryBuilder

Attributes

connection[R]
record[R]

Public Class Methods

new(record, connection) click to toggle source
# File lib/atomic_json/query_builder.rb, line 14
def initialize(record, connection)
  @record = record
  @connection = connection
end

Public Instance Methods

build(attributes, touch) click to toggle source
# File lib/atomic_json/query_builder.rb, line 19
    def build(attributes, touch)
      <<~SQL
        UPDATE #{quote_table_name(record.class.table_name)}
        SET #{build_set_subquery(attributes, touch)}
        WHERE id = #{quote(record.id)};
      SQL
    end

Private Instance Methods

build_set_subquery(attributes, touch) click to toggle source
# File lib/atomic_json/query_builder.rb, line 29
def build_set_subquery(attributes, touch)
  updates = json_updates_agg(attributes)
  updates << timestamp_update_string if touch && record.has_attribute?(:updated_at)
  updates.join(',')
end
json_deep_merge(target, payload) click to toggle source
# File lib/atomic_json/query_builder.rb, line 45
def json_deep_merge(target, payload)
  loop do
    keys, value = traverse_payload(Hash[*payload.shift])
    target = jsonb_set_query_string(target, keys, value)
    break target if payload.empty?
  end
end
json_updates_agg(attributes) click to toggle source
# File lib/atomic_json/query_builder.rb, line 35
def json_updates_agg(attributes)
  attributes.map do |column, payload|
    "#{quote_column_name(column)} = #{json_deep_merge(column, payload)}"
  end
end
jsonb_set_query_string(target, keys, value) click to toggle source
# File lib/atomic_json/query_builder.rb, line 66
      def jsonb_set_query_string(target, keys, value)
        <<~EOF
          jsonb_set(
            #{target}::jsonb,
            #{jsonb_quote_keys(keys)},
            #{multi_value_hash?(value) ? concatenation(target, keys, value) : jsonb_quote_value(value)}
          )::jsonb
        EOF
      end
multi_value_hash?(value) click to toggle source
# File lib/atomic_json/query_builder.rb, line 76
def multi_value_hash?(value)
  value.is_a?(Hash) && value.keys.count > 1
end
single_value_hash?(value) click to toggle source
# File lib/atomic_json/query_builder.rb, line 80
def single_value_hash?(value)
  value.is_a?(Hash) && value.keys.count == 1
end
timestamp_update_string() click to toggle source
# File lib/atomic_json/query_builder.rb, line 41
def timestamp_update_string
  "#{quote_column_name(:updated_at)} = #{quote(Time.now)}"
end
traverse_payload(key_value_pair, keys = []) click to toggle source

Traverse the Hash payload, incrementally aggregating all hash keys into an array and use the last child as value

# File lib/atomic_json/query_builder.rb, line 57
def traverse_payload(key_value_pair, keys = [])
  loop do
    key, val = key_value_pair.flatten
    keys << key.to_s
    break [keys, val] unless single_value_hash?(val)
    key_value_pair = val
  end
end