Class: Graphql::HydrateQuery

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/hydrate_query.rb

Instance Method Summary collapse

Constructor Details

#initialize(model, context, order_by: nil, filter: nil, id: nil, user: nil, page: nil, per_page: 10) ⇒ HydrateQuery



7
8
9
10
11
12
13
14
15
16
17
# 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

Instance Method Details

#activerecord_model?(name) ⇒ Boolean



83
84
85
86
87
88
89
90
# 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) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
# 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) ⇒ Object



72
73
74
75
76
77
78
79
80
81
# 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) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 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) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
# 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_nameObject



117
118
119
# File 'lib/graphql/hydrate_query.rb', line 117

def model_name
  @model.class.to_s.split('::').first.underscore.pluralize
end

#parse_fields(irep_node) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
# 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) ⇒ Object



40
41
42
# 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

#runObject



19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 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) ⇒ Object



34
35
36
37
38
# 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