class GlobalController < ApplicationController
include ExceptionHandler include Response def default_per_page 25 end def model self.class.to_s.split("::").select {|e| /Controller/.match(e) }.first.chomp("Controller").singularize.constantize end def index resp = index_response past_pages = resp[:last_page] < resp[:current_page] error = {error: "Past the amount of pages available"} status = past_pages ? :bad_request : :ok data = past_pages ? error : resp data = handle_includes(data) if params[:include] && !past_pages render_json(data, status) end def show data = model.find(params[:id] || 0) data = handle_includes(data) if params[:include] render_json(data, :ok) end def create data = model.create(create_params) render_json(data, :created) end def update data = model.where(id: params[:id] || 0).update(update_params).first render_json(data, :ok) end def destroy model.destroy(params[:id] || 0) render_json(nil, :no_content) end def bulk_csv_create data = model.create(csv_to_json) render_json(data, :created) end def bulk_create data = model.create(bulk_create_params[:bulk]) render_json(data, :created) end def bulk_update data = model.where(id: bulk_update_params[:bulk].map {|e| e[:id] }).update(bulk_update_params[:bulk]) render_json(data, :ok) end def bulk_destroy ids = comma_separated(:ids) are_ids = array_of_integers(ids) if ids.is_a?(Array) && are_ids array = model.where(id: ids) if array.length == ids.length array.delete_all render_json(nil, :no_content) else render_json({ error: "Not all ids are valid" }, :bad_request) end else render_json({ error: "Must pass in a string of ids that are comma separated" }, :bad_request) end end private def array_of_integers array array.all? { |e| is_i?(e) } end def is_i? string !!(string =~ /\A[-+]?[0-9]+\z/) end def csv_to_json param_key=:file, separated_by="," lines = params[param_key].split("\n") keys = lines[0].split(separated_by) rows = lines.slice(1).map {|e| e.split(separated_by) } rows.map {|e| e.each_with_index.inject({}) {|acc, (e, i)| acc.merge(:"#{keys[i]}" => e) } } end def create_params bl = array_to_hash(black_list_create) params.permit(*get_model_key.reject {|e| bl[e.to_sym] }) end def update_params bl = array_to_hash(black_list_update) params.permit(*get_model_key.reject {|e| bl[e.to_sym] }) end def bulk_create_params params.permit(bulk: get_model_key) end def bulk_update_params params.permit(bulk: get_model_key) end def bulk_destroy_params params.permit(bulk: [:id]) end def black_list_create %i[id created_at updated_at] end def black_list_update %i[id created_at updated_at] end def array_to_hash array array.each_with_object({}) do |e, acc| acc[e] = true acc end end def handle_pagination limit = (params[:limit] || default_per_page).to_i offset = (params[:offset] || 0).to_i page = (params[:page] || 1).to_i order = params[:order] ? get_order : "id ASC" data = model.limit(limit).offset(offset).offset((page - 1) * limit) data = data.where(get_where) if params[:where] data = data.includes(*get_includes) if params[:include] data = data.order(order) data = data.all data end def handle_pagination_count data = model data = data.where(get_where) if params[:where] data.count end def handle_includes data data.to_json(include: get_includes) end def index_response page = (params[:page] || 1).to_i per_page = (params[:limit] || default_per_page).to_i total = handle_pagination_count path = request.original_url path_path = add_pg_qs(path) last = (total / per_page.to_f).ceil nxt = (page + 1) > last ? nil : (page + 1) prev = (page - 1) == 0 ? nil : (page - 1) last = last == 0 ? 1 : last data = handle_pagination data_first = data.first data_last = data.last { data: data, from: data_first ? data_first.id : nil, to: data_last ? data_last.id : nil, total: total, path: path, current_page: page, per_page: per_page, last_page: last, first_page_url: path_path + "1", last_page_url: path_path + last.to_s, next_page_url: nxt ? (path_path + nxt.to_s) : nil, prev_page_url: prev ? (path_path + prev.to_s) : nil } end def add_pg_qs str has_qs = /\?/.match(str) return "#{str}?page=" unless has_qs before_qs, after = str.split("?") after_qs = after.split("&").reject {|e| /page\=/.match(e) } after_qs.push("page=") "#{before_qs}?#{after_qs.join('&')}" end def get_includes comma_separated(:include).map do |e| semi = e.split(":") semi.length > 1 ? array_depth(semi) : semi.first.to_sym end end def array_depth(array, acc={}) if array.length > 2 key = array.shift acc[key.to_sym] = array_depth(array, {}) else key, val = array acc[key.to_sym] = val.to_sym end acc end def get_order params[:order].split(",").flat_map {|e| e.split(":") }.join(" ") end def get_where arrays = params[:where].split(",").map {|e| e.split(":") } arrays.each_with_object({}) do |item, acc| key, val = item acc[key] = val end end def comma_separated key params[key].split(",") end def get_model_key model.columns.map {|e| e.name.to_sym } end
end