Module: Motor::ApiQuery::BuildJson

Defined in:
lib/motor/api_query/build_json.rb

Class Method Summary collapse

Class Method Details

.assign_fields_params!(json_params, model, params, current_ability, models_index) ⇒ void

This method returns an undefined value.

Parameters:

  • json_params (Hash)
  • model (Class<ActiveRecord::Base>)
  • params (Hash)
  • current_ability (CanCan::Ability)
  • models_index (Hash)

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/motor/api_query/build_json.rb', line 46

def assign_fields_params!(json_params, model, params, current_ability, models_index)
  return if params[:fields].blank?

  params[:fields].each do |key, fields|
    fields_model = models_index[key]

    next unless model

    fields = fields.split(',') if fields.is_a?(String)

    fields_hash = fields_model == model ? json_params : find_key_in_params(json_params, key)

    fields_hash.merge!(build_fields_hash(fields_model, fields, current_ability))
  end
end

.build_fields_hash(model, fields, current_ability) ⇒ Hash

Parameters:

  • model (Class<ActiveRecord::Base>)
  • fields (Hash)
  • current_ability (CanCan::Ability)

Returns:

  • (Hash)

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/motor/api_query/build_json.rb', line 66

def build_fields_hash(model, fields, current_ability)
  return { 'methods' => fields } unless model

  column_names = model.column_names.map(&:to_sym)
  instance_methods = model.instance_methods
  permitted_attributes = current_ability.permitted_attributes(:read, model)
  is_permitted_all = column_names == permitted_attributes

  fields_hash = { 'only' => [], 'methods' => [] }

  fields.each_with_object(fields_hash) do |field, acc|
    field_symbol = field.to_sym

    next if !is_permitted_all && permitted_attributes.exclude?(field_symbol)

    if model.columns_hash[field]
      acc['only'] << field
    elsif instance_methods.include?(field_symbol)
      acc['methods'] << field
    end
  end
end

.build_hash_from_string_path(string_path) ⇒ Hash

Parameters:

  • string_path (String)

Returns:

  • (Hash)

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/motor/api_query/build_json.rb', line 148

def build_hash_from_string_path(string_path)
  string_path.split(',').reduce({}) do |accumulator, path|
    hash = {}

    path.split('.').reduce(hash) do |acc, part|
      acc_hash = {}

      acc[part] = acc_hash

      acc_hash
    end

    accumulator.deep_merge(hash)
  end
end

.build_include_hash(include_params) ⇒ Hash

Parameters:

  • include_params (Hash)

Returns:

  • (Hash)

30
31
32
33
34
35
36
37
38
# File 'lib/motor/api_query/build_json.rb', line 30

def build_include_hash(include_params)
  return {} if include_params.blank?

  if include_params.is_a?(String)
    build_hash_from_string_path(include_params)
  else
    include_params
  end
end

.build_models_index(model, includes_hash) ⇒ Hash

Parameters:

  • model (Class<ActiveRecord::Base>)
  • includes_hash (Hash)

Returns:

  • (Hash)

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/motor/api_query/build_json.rb', line 128

def build_models_index(model, includes_hash)
  default_index = {
    model.name.underscore => model,
    model.name.underscore.split('/').last => model
  }

  includes_hash.reduce(default_index) do |acc, (key, value)|
    reflection = model.reflections[key]

    next acc unless reflection
    next acc if reflection.polymorphic?

    acc[key] = reflection.klass

    acc.merge(build_models_index(reflection.klass, value))
  end
end

.call(rel, params, current_ability = Motor::CancanUtils::CanManageAll.new) ⇒ Hash

Parameters:

  • rel (ActiveRecord::Base, ActiveRecord::Relation)
  • params (Hash)
  • current_ability (CanCan::Ability) (defaults to: Motor::CancanUtils::CanManageAll.new)

Returns:

  • (Hash)

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/motor/api_query/build_json.rb', line 12

def call(rel, params, current_ability = Motor::CancanUtils::CanManageAll.new)
  rel = rel.none if limit_zero_params?(params)
  rel = rel.preload_associations_lazily if rel.is_a?(ActiveRecord::Relation)

  model = rel.is_a?(ActiveRecord::Relation) ? rel.klass : rel.class

  include_hash = build_include_hash(params['include'])
  models_index = build_models_index(model, include_hash)

  json_params = normalize_include_params(include_hash)

  assign_fields_params!(json_params, model, params, current_ability, models_index)

  rel.as_json(json_params.with_indifferent_access)
end

.find_key_in_params(params, key) ⇒ Hash

Parameters:

  • params (Hash)
  • key (String)

Returns:

  • (Hash)

92
93
94
95
96
97
98
99
100
101
# File 'lib/motor/api_query/build_json.rb', line 92

def find_key_in_params(params, key)
  params = params['include']

  return {} if params.blank?
  return params[key] if params[key]

  params.keys.reduce(nil) do |acc, k|
    acc || find_key_in_params(params[k], key)
  end
end

.limit_zero_params?(params) ⇒ Boolean

Parameters:

  • params (Hash)

Returns:

  • (Boolean)

166
167
168
# File 'lib/motor/api_query/build_json.rb', line 166

def limit_zero_params?(params)
  params.dig(:page, :limit).yield_self { |limit| limit.present? && limit.to_i.zero? }
end

.normalize_include_params(params) ⇒ Hash

Parameters:

  • params (Hash)

Returns:

  • (Hash)

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/motor/api_query/build_json.rb', line 105

def normalize_include_params(params)
  case params
  when Array
    params.index_with do |_|
      { 'include' => {} }
    end
  when String
    { params => { 'include' => {} } }
  when Hash
    include_hash =
      params.transform_values do |value|
        normalize_include_params(value)
      end

    { 'include' => include_hash }
  else
    raise ArgumentError, "Wrong include param type #{params.class}"
  end
end