module ActiveRecordExtended::QueryMethods::Json
Constants
- JSON_QUERY_METHODS
Public Instance Methods
Appends a hash literal to the calling relations response
Arguments: Requires an Array or Hash set of values
Options:
- as: [Symbol or String] (default="results"): What the column will be aliased to
Example:
- Supplying inputs as a Hash query = User.json_build_literal(number: 1, last_name: "json", pi: 3.14) query.take.results #=> { "number" => 1, "last_name" => "json", "pi" => 3.14 } - Supplying inputs as an Array query = User.json_build_literal(:number, 1, :last_name, "json", :pi, 3.14) query.take.results #=> { "number" => 1, "last_name" => "json", "pi" => 3.14 }
# File lib/active_record_extended/query_methods/json.rb, line 318 def json_build_literal(*args) JsonChain.new(spawn).json_build_literal!(args) end
Creates a json response object that will convert all subquery results into a json compatible response
Arguments:
key: [Symbol or String]: What should this response return as from: [String, Arel, or ActiveRecord::Relation] : A subquery that can be nested into the top-level from clause
Options:
- as: [Symbol or String] (default="results"): What the column will be aliased to - value: [Symbol or String] (defaults=[key]): How the response should handel the json value return
Example:
- Generic example: subquery = Group.select(:name, :category_id).where("user_id = users.id") User.select(:name, email).select_row_to_json(subquery, as: :users_groups, cast_with: :array) #=> [<#User name:.., email:.., users_groups: [{ name: .., category_id: .. }, ..]] - Setting a custom value: Before: subquery = User.select(:name).where(id: 100..110).group(:name) User.build_json_object(:gang_members, subquery).take.results["gang_members"] #=> nil After: User.build_json_object(:gang_members, subquery, value: "COALESCE(array_agg(\"gang_members\"), 'BANG!')") .take .results["gang_members"] #=> "BANG!"
# File lib/active_record_extended/query_methods/json.rb, line 287 def json_build_object(key, from, **options) options[:key] = key options[:from] = from JsonChain.new(spawn).json_build_object!(options) end
# File lib/active_record_extended/query_methods/json.rb, line 322 def jsonb_build_literal(*args) JsonChain.new(spawn).jsonb_build_literal!(args) end
# File lib/active_record_extended/query_methods/json.rb, line 293 def jsonb_build_object(key, from, **options) options[:key] = key options[:from] = from JsonChain.new(spawn).jsonb_build_object!(options) end
Appends a select statement that contains a subquery that is converted to a json response
Arguments:
- from: [String, Arel, or ActiveRecord::Relation] A subquery that can be nested into a ROW_TO_JSON clause
Options:
- as: [Symbol or String] (default="results"): What the column will be aliased to - key: [Symbol or String] (default=[random letter]) What the row clause will be set as. - This is useful if you would like to add additional mid-level clauses (see mid-level scope example) - cast_with [Symbol or Array of symbols]: Actions to transform your query * :to_jsonb * :array * :array_agg (including just :array with this option will favor :array_agg) * :distinct (auto applies :array_agg & :to_jsonb) - order_by [Symbol or hash]: Applies an ordering operation (similar to ActiveRecord #order) - NOTE: this option will be ignored if you need to order a DISTINCT Aggregated Array, since postgres will thrown an error.
Examples:
subquery = Group.select(:name, :category_id).where("user_id = users.id") User.select(:name, email).select_row_to_json(subquery, as: :users_groups, cast_with: :array) #=> [<#User name:.., email:.., users_groups: [{ name: .., category_id: .. }, ..]] - Adding mid-level scopes: subquery = Group.select(:name, :category_id) User.select_row_to_json(subquery, key: :group, cast_with: :array) do |scope| scope.where(group: { name: "Nerd Core" }) end #=> ```sql SELECT ARRAY( SELECT ROW_TO_JSON("group") FROM(SELECT name, category_id FROM groups) AS group WHERE group.name = 'Nerd Core' ) ```
-
Array of JSONB objects
subquery = Group.select(:name, :category_id) User.select_row_to_json(subquery, key: :group, cast_with: [:array, :to_jsonb]) do |scope|
scope.where(group: { name: "Nerd Core" })
end #=> “`sql
SELECT ARRAY( SELECT TO_JSONB(ROW_TO_JSON("group")) FROM(SELECT name, category_id FROM groups) AS group WHERE group.name = 'Nerd Core' )
“`
-
Distinct Aggregated Array
subquery = Group.select(:name, :category_id) User.select_row_to_json(subquery, key: :group, cast_with: [:array_agg, :distinct]) do |scope|
scope.where(group: { name: "Nerd Core" })
end #=> “`sql
SELECT ARRAY_AGG(DISTINCT ( SELECT TO_JSONB(ROW_TO_JSON("group")) FROM(SELECT name, category_id FROM groups) AS group WHERE group.name = 'Nerd Core' ))
“`
-
Ordering a Non-aggregated Array
subquery = Group.select(:name, :category_id) User.select_row_to_json(subquery, key: :group, cast_with: :array, order_by: { group: { name: :desc } }) #=> ```sql SELECT ARRAY( SELECT ROW_TO_JSON("group") FROM(SELECT name, category_id FROM groups) AS group ORDER BY group.name DESC ) ```
-
Ordering an Aggregated Array
Subquery = Group.select(:name, :category_id) User .joins(:people_groups) .select_row_to_json( subquery, key: :group, cast_with: :array_agg, order_by: { people_groups: :category_id } ) #=> ```sql SELECT ARRAY_AGG(( SELECT ROW_TO_JSON("group") FROM(SELECT name, category_id FROM groups) AS group ORDER BY group.name DESC ) ORDER BY people_groups.category_id ASC) ```
# File lib/active_record_extended/query_methods/json.rb, line 248 def select_row_to_json(from = nil, **options, &block) from.is_a?(Hash) ? options.merge!(from) : options.reverse_merge!(from: from) options.compact! raise ArgumentError.new("Required to provide a non-nilled from clause") unless options.key?(:from) JsonChain.new(spawn).row_to_json!(**options, &block) end