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

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 }


212
213
214
# File 'lib/active_record_extended/query_methods/json.rb', line 212

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_as_array: true)
   #=> [<#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!"
  • Adding mid-level scopes

    subquery = Group.select(:name, :category_id) User.select_row_to_json(subquery, key: :group, cast_as_array: true) 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'
      )
    ```
    


181
182
183
184
185
# File 'lib/active_record_extended/query_methods/json.rb', line 181

def json_build_object(key, from, **options)
  options[:key]  = key
  options[:from] = from
  JsonChain.new(spawn).json_build_object!(options)
end

#jsonb_build_literal(*args) ⇒ Object



216
217
218
# File 'lib/active_record_extended/query_methods/json.rb', line 216

def jsonb_build_literal(*args)
  JsonChain.new(spawn).jsonb_build_literal!(args)
end

#jsonb_build_object(key, from, **options) ⇒ Object



187
188
189
190
191
# File 'lib/active_record_extended/query_methods/json.rb', line 187

def jsonb_build_object(key, from, **options)
  options[:key]  = key
  options[:from] = from
  JsonChain.new(spawn).jsonb_build_object!(options)
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_as_array [boolean] (default=false): Determines if the query should be nested inside an Array() function

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_as_array: true)
   #=> [<#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_as_array: true) do |scope|
   scope.where(group: { name: "Nerd Core" })
 end

Raises:

  • (ArgumentError)


128
129
130
131
132
133
# File 'lib/active_record_extended/query_methods/json.rb', line 128

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, "Required to provide a non-nilled from clause" unless options.key?(:from)
  JsonChain.new(spawn).row_to_json!(**options, &block)
end