Last active
November 5, 2017 11:33
-
-
Save Altech/34691e415fef894e2201e24bfd7c0a73 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Api::ControllerHelpers | |
extend ActiveSupport::Concern | |
included do | |
include InstanceMethods | |
before_action :prepare_restful_params | |
end | |
module InstanceMethods | |
def prepare_restful_params | |
@fields, @include = prepare_for_fields_and_include( | |
fields_param: process_param_as_array(params[:fields]), | |
include_param: process_param_as_array(params[:include]), | |
) unless debug_mode? | |
end | |
# @example | |
# prepare_for_fields_and_include( | |
# fields_param: ['name', 'articles.title', 'articles.url'], | |
# include_param: ['articles', 'articles.image'] | |
# ) | |
# #=> | |
# # [ | |
# # [:id, :name], | |
# # { | |
# # articles: { | |
# # fields: [:id, :title], | |
# # image: { | |
# # fields: [:id, :url] | |
# # } | |
# # } | |
# # } | |
# # ] | |
def prepare_for_fields_and_include(fields_param: [], include_param: []) | |
fields_param = fields_param.map{ |v| v.split('.').map(&:to_sym) } | |
include_param = include_param.map{ |v| v.split('.').map(&:to_sym) } | |
include = include_param.sort_by(&:size).inject({}) do |include, associations| | |
hash = include | |
associations.each_with_index do |association, i| | |
if i == associations.size - 1 | |
hash[association] = {} | |
else | |
hash = hash[association] | |
if hash.nil? | |
raise Api::ImplicitIncludeError.new(associations[0..i]) | |
end | |
end | |
end | |
include | |
end | |
fields = fields_param.select { |f| f.size == 1 }.flatten | |
nested = fields_param.select { |f| f.size > 1 } | |
fields << :id unless fields.include?(:id) | |
nested.each do |f| | |
associations, field = f[0..-2], f[-1] | |
hash = include.dig(*associations) | |
if hash.nil? | |
raise Api::UnincludedFieldError.new(field, associations) | |
end | |
hash[:fields] ||= [:id] | |
hash[:fields] << f.last unless hash[:fields].include?(f.last) | |
end | |
return fields, include | |
end | |
# To accept both comma-separated array and brackets array. | |
# And treat nil as empty array. | |
# | |
# comma-separated array: fields=foo,bar,baz | |
# brackets array: fields[]=foo&fields[]=bar&fields[]=baz | |
def process_param_as_array(param) | |
case param | |
when nil | |
[] | |
when Array | |
param | |
when String | |
param.split(',') | |
end | |
end | |
def debug_mode? | |
params[:debug].to_b && !Rails.env.production? | |
end | |
def preload_for(rel) | |
Api::Preloader.preload_for(rel, @fields, @include) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment