class Graphql::HydrateQuery

Public Class Methods

new(model, context, order_by: nil, filter: nil, id: nil, user: nil, page: nil, per_page: 10) click to toggle source
# File lib/graphql/hydrate_query.rb, line 7
def initialize(model, context, order_by: nil, filter: nil, id: nil, user: nil, page: nil, per_page: 10)
  @context = context
  @filter = filter
  @order_by = order_by
  @model = model
  @models = [model_name.singularize.camelize]
  @id = id
  @user = user
  @page = page
  @per_page = per_page
end

Public Instance Methods

activerecord_model?(name) click to toggle source
# File lib/graphql/hydrate_query.rb, line 83
def activerecord_model?(name)
  class_name = name.to_s.singularize.camelize
  begin
    class_name.constantize.ancestors.include?(ApplicationRecord)
  rescue NameError
    false
  end
end
evaluate_model(parent, child) click to toggle source
# File lib/graphql/hydrate_query.rb, line 92
def evaluate_model(parent, child)
  return unless parent.reflect_on_association(child)

  child_class_name = parent.reflect_on_association(child).class_name
  parent_class_name = parent.to_s.singularize.camelize

  return child_class_name.constantize if activerecord_model?(child_class_name)

  return unless activerecord_model?(parent_class_name)

  parent_class_name.constantize.reflections[child.to_s.underscore]&.klass
end
fetch_ids_from_relation(hash) click to toggle source
# File lib/graphql/hydrate_query.rb, line 72
def fetch_ids_from_relation(hash)
  hash.select { |k, _| k.ends_with?('_ids') }.each do |(k, _)|
    collection_name = k.gsub('_ids', '').pluralize
    if hash[collection_name].blank?
      hash[collection_name] = { 'id' => nil }
    else
      hash[collection_name]['id'] = nil
    end
  end
end
hash_to_array_of_hashes(hash, parent_class) click to toggle source
# File lib/graphql/hydrate_query.rb, line 56
def hash_to_array_of_hashes(hash, parent_class)
  return if parent_class.nil? || hash.nil?

  hash['id'] = nil if hash['id'].blank?
  fetch_ids_from_relation(hash)

  hash.each_with_object([]) do |(k, v), arr|
    next arr << k if parent_class.new.attributes.key?(k)
    next arr << v if parent_class.new.attributes.key?(v)

    klass = evaluate_model(parent_class, k)
    @models << klass.to_s unless @models.include?(klass.to_s)
    arr << { k.to_sym => hash_to_array_of_hashes(v, klass) } if klass.present? && v.present?
  end
end
hash_to_struct(hash, parent_model) click to toggle source
# File lib/graphql/hydrate_query.rb, line 44
def hash_to_struct(hash, parent_model)
  hash.each_with_object(OpenStruct.new) do |(k, v), struct|
    m = evaluate_model(parent_model, k)

    next struct[k.to_sym] = plucked_attr_to_structs(v, m) if v.is_a?(Array) && m

    next struct[k.to_sym] = hash_to_struct(v, m) if v.is_a?(Hash) && m

    struct[k.to_sym] = v
  end
end
model_name() click to toggle source
# File lib/graphql/hydrate_query.rb, line 117
def model_name
  @model.class.to_s.split('::').first.underscore.pluralize
end
parse_fields(irep_node) click to toggle source
# File lib/graphql/hydrate_query.rb, line 105
def parse_fields(irep_node)
  fields = irep_node&.scoped_children&.values&.first
  if fields.key?('edges')
    fields = fields['edges'].scoped_children.values.first['node']&.scoped_children&.values&.first
  end
  return if fields.blank?

  fields.each_with_object({}) do |(k, v), h|
    h[k] = v.scoped_children == {} ? v.definition.name : parse_fields(v)
  end
end
plucked_attr_to_structs(arr, parent_model) click to toggle source
# File lib/graphql/hydrate_query.rb, line 40
def plucked_attr_to_structs(arr, parent_model)
  arr.map { |e| hash_to_struct(e, parent_model) }
end
run() click to toggle source
# File lib/graphql/hydrate_query.rb, line 19
def run
  @model = @model.where(transform_filter(@filter)) if @filter
  @model = @model.order(@order_by) if @order_by

  @model = @model.limit(@per_page) if @per_page
  @model = @model.offset(@per_page * (@page - 1)) if @page

  @model = @model.where(id: @id) if @id
  plucked = DeepPluck::Model.new(@model.visible_for(user: @user), user: @user).add(
    hash_to_array_of_hashes(parse_fields(@context&.irep_node), @model)
  ).load_all
  result = plucked_attr_to_structs(plucked, model_name.singularize.camelize.constantize)&.compact
  @id ? result.first : result
end
transform_filter(filter) click to toggle source
# File lib/graphql/hydrate_query.rb, line 34
def transform_filter(filter)
  parsed_filter = RKelly::Parser.new.parse(filter.gsub('like', ' | ')).to_ecma
  parsed_filter.gsub(' | ', ' like ').
    gsub('||', 'OR').gsub('&&', 'AND').gsub('===', '=').gsub('==', '=').delete(';')
end