Module: ActiveRecordExtended::QueryMethods::Json
- Defined in:
- lib/active_record_extended/query_methods/json.rb
Defined Under Namespace
Classes: JsonChain
Constant Summary collapse
- JSON_QUERY_METHODS =
[ :select_row_to_json, :json_build_object, :jsonb_build_object, :json_build_literal, :jsonb_build_literal ].freeze
Instance Method Summary collapse
-
#json_build_literal(*args) ⇒ Object
Appends a hash literal to the calling relations response.
-
#json_build_object(key, from, **options) ⇒ Object
Creates a json response object that will convert all subquery results into a json compatible response.
- #jsonb_build_literal(*args) ⇒ Object
- #jsonb_build_object(key, from, **options) ⇒ Object
-
#select_row_to_json(from = nil, **options, &block) ⇒ Object
Appends a select statement that contains a subquery that is converted to a json response.
Instance Method Details
#json_build_literal(*args) ⇒ Object
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 }
318 319 320 |
# File 'lib/active_record_extended/query_methods/json.rb', line 318 def json_build_literal(*args) JsonChain.new(spawn).json_build_literal!(args) end |
#json_build_object(key, from, **options) ⇒ Object
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!"
287 288 289 290 291 |
# File 'lib/active_record_extended/query_methods/json.rb', line 287 def json_build_object(key, from, **) [:key] = key [:from] = from JsonChain.new(spawn).json_build_object!() end |
#jsonb_build_literal(*args) ⇒ Object
322 323 324 |
# File 'lib/active_record_extended/query_methods/json.rb', line 322 def jsonb_build_literal(*args) JsonChain.new(spawn).jsonb_build_literal!(args) end |
#jsonb_build_object(key, from, **options) ⇒ Object
293 294 295 296 297 |
# File 'lib/active_record_extended/query_methods/json.rb', line 293 def jsonb_build_object(key, from, **) [:key] = key [:from] = from JsonChain.new(spawn).jsonb_build_object!() end |
#select_row_to_json(from = nil, **options, &block) ⇒ Object
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)
```
248 249 250 251 252 253 254 |
# File 'lib/active_record_extended/query_methods/json.rb', line 248 def select_row_to_json(from = nil, **, &block) from.is_a?(Hash) ? .merge!(from) : .reverse_merge!(from: from) .compact! raise ArgumentError.new("Required to provide a non-nilled from clause") unless .key?(:from) JsonChain.new(spawn).row_to_json!(**, &block) end |