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