class ActiveRecordExtended::QueryMethods::Json::JsonChain
Constants
- ARRAY_OPTIONS
- DEFAULT_ALIAS
- TO_JSONB_OPTIONS
Public Class Methods
new(scope)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 22 def initialize(scope) @scope = scope end
Public Instance Methods
json_build_literal!(*args)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 41 def json_build_literal!(*args) options = json_object_options(args, only: [:values, :col_alias]) build_json_literal(Arel::Nodes::JsonBuildObject, **options) end
json_build_object!(*args)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 31 def json_build_object!(*args) options = json_object_options(args, except: [:values, :cast_with, :order_by]) build_json_object(Arel::Nodes::JsonBuildObject, **options) end
jsonb_build_literal!(*args)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 46 def jsonb_build_literal!(*args) options = json_object_options(args, only: [:values, :col_alias]) build_json_literal(Arel::Nodes::JsonbBuildObject, **options) end
jsonb_build_object!(*args)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 36 def jsonb_build_object!(*args) options = json_object_options(args, except: [:values, :cast_with, :order_by]) build_json_object(Arel::Nodes::JsonbBuildObject, **options) end
row_to_json!(**args, &block)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 26 def row_to_json!(**args, &block) options = json_object_options(args, except: [:values, :value]) build_row_to_json(**options, &block) end
Private Instance Methods
build_json_literal(arel_klass, values:, col_alias: DEFAULT_ALIAS)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 53 def build_json_literal(arel_klass, values:, col_alias: DEFAULT_ALIAS) json_values = flatten_to_sql(values.to_a) { |value| literal_key(value) } col_alias = double_quote(col_alias) json_build_obj = arel_klass.new(json_values) @scope.select(nested_alias_escape(json_build_obj, col_alias)) end
build_json_object(arel_klass, from:, key: key_generator, value: nil, col_alias: DEFAULT_ALIAS)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 60 def build_json_object(arel_klass, from:, key: key_generator, value: nil, col_alias: DEFAULT_ALIAS) tbl_alias = double_quote(key) col_alias = double_quote(col_alias) col_key = literal_key(key) col_value = to_arel_sql(value.presence || tbl_alias) json_build_object = arel_klass.new(to_sql_array(col_key, col_value)) unless /".+"/.match?(col_value) warn("`#{col_value}`: the `value` argument should contain a double quoted key reference for safety") end @scope.select(nested_alias_escape(json_build_object, col_alias)).from(nested_alias_escape(from, tbl_alias)) end
build_row_to_json(from:, **options, &block)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 74 def build_row_to_json(from:, **options, &block) key = options[:key] row_to_json = ::Arel::Nodes::RowToJson.new(double_quote(key)) row_to_json = ::Arel::Nodes::ToJsonb.new(row_to_json) if options.dig(:cast_with, :to_jsonb) dummy_table = from_clause_constructor(from, key).select(row_to_json) dummy_table = dummy_table.instance_eval(&block) if block return dummy_table if options[:col_alias].blank? query = wrap_row_to_json(dummy_table, options) @scope.select(query) end
casting_options(cast_with)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 132 def casting_options(cast_with) return {} if cast_with.blank? skip_convert = [Symbol, TrueClass, FalseClass] Array(cast_with).compact.each_with_object({}) do |arg, options| arg = arg.to_sym unless skip_convert.include?(arg.class) options[:to_jsonb] |= TO_JSONB_OPTIONS.include?(arg) options[:array] |= ARRAY_OPTIONS.include?(arg) options[:array_agg] |= arg == :array_agg options[:distinct] |= arg == :distinct end end
json_object_options(args, except: [], only: [])
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 101 def json_object_options(args, except: [], only: []) # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity options = {} lean_opts = lambda do |key, &block| if only.present? options[key] ||= block.call if only.include?(key) elsif !except.include?(key) options[key] ||= block.call end end flatten_safely(args) do |arg| next if arg.nil? if arg.is_a?(Hash) lean_opts.call(:key) { arg.fetch(:key, key_generator) } lean_opts.call(:value) { arg[:value].presence } lean_opts.call(:col_alias) { arg[:as] } lean_opts.call(:order_by) { order_by_expression(arg[:order_by]) } lean_opts.call(:from) { arg[:from].tap { |from_clause| pipe_cte_with!(from_clause) } } lean_opts.call(:cast_with) { casting_options(arg[:cast_with]) } end unless except.include?(:values) options[:values] ||= [] options[:values] << (arg.respond_to?(:to_a) ? arg.to_a : arg) end end options.tap(&:compact!) end
wrap_row_to_json(dummy_table, options)
click to toggle source
# File lib/active_record_extended/query_methods/json.rb, line 87 def wrap_row_to_json(dummy_table, options) cast_opts = options[:cast_with] col_alias = options[:col_alias] order_by = options[:order_by] if cast_opts[:array_agg] || cast_opts[:distinct] wrap_with_agg_array(dummy_table, col_alias, order_by: order_by, distinct: cast_opts[:distinct]) elsif cast_opts[:array] wrap_with_array(dummy_table, col_alias, order_by: order_by) else nested_alias_escape(dummy_table, col_alias) end end