module StandardAPI

Public Class Methods

included(klass) click to toggle source
# File lib/standard_api.rb, line 16
def self.included(klass)
  klass.hide_action :current_mask
  klass.helper_method :includes, :orders
  klass.prepend_view_path(File.join(File.dirname(__FILE__), 'standard_api', 'views'))
end

Public Instance Methods

calculate() click to toggle source
# File lib/standard_api.rb, line 27
def calculate
  @calculations = resources.reorder(nil).pluck(*calculate_selects).map do |c|
    if c.is_a?(Array)
      c.map { |v| v.is_a?(BigDecimal) ? v.to_f : v }
    else
      c.is_a?(BigDecimal) ? c.to_f : c
    end
  end
  render json: @calculations
end
create() click to toggle source
# File lib/standard_api.rb, line 43
def create
  @record = model.new(model_params)
  instance_variable_set("@#{model.model_name.singular}", @record)
  render :show, status: @record.save ? :created : :bad_request
end
current_mask() click to toggle source

Override if you want to support masking

# File lib/standard_api.rb, line 61
def current_mask
  @current_mask ||= {}
end
destroy() click to toggle source
# File lib/standard_api.rb, line 55
def destroy
  resources.find(params[:id]).destroy!
  render nothing: true, status: :no_content
end
index() click to toggle source
# File lib/standard_api.rb, line 22
def index
  @records = resources.limit(params[:limit]).offset(params[:offset]).sort(orders)
  instance_variable_set("@#{model.model_name.plural}", @records)
end
show() click to toggle source
# File lib/standard_api.rb, line 38
def show
  @record = resources.find(params[:id])
  instance_variable_set("@#{model.model_name.singular}", @record)
end
update() click to toggle source
# File lib/standard_api.rb, line 49
def update
  @record = resources.find(params[:id])
  instance_variable_set("@#{model.model_name.singular}", @record)
  render :show, status: @record.update_attributes(model_params) ? :ok : :bad_request
end

Private Instance Methods

calculate_selects() click to toggle source

Used in calculate

{ count: :id }
{ count: ‘*’ }
{ count: ‘*’, maximum: :id, minimum: :id }
{ count: ‘*’ }, { maximum: :id }, { minimum: :id }

TODO: Sanitize (normalize_select_params(params, model))

# File lib/standard_api.rb, line 141
def calculate_selects
  return @selects if defined?(@selects)

  functions = ['minimum', 'maximum', 'average', 'sum', 'count']
  @selects = []
  Array(params[:select]).each do |select|
    select.each do |func, column|
      column = column == '*' ? Arel.star : column.to_sym
      if functions.include?(func.to_s.downcase)
        @selects << (model.arel_table[column.to_sym].send(func).to_sql)
      end
    end
  end

  @selects
end
includes() click to toggle source

TODO: sanitize includes

# File lib/standard_api.rb, line 89
def includes
  params[:include] || []
end
model() click to toggle source
# File lib/standard_api.rb, line 67
def model
  return @model if defined?(@model)
  @model = self.class.name.sub(/Controller\z/, '').singularize.camelize.constantize
end
model_includes() click to toggle source
# File lib/standard_api.rb, line 76
def model_includes
  self.send "#{model.model_name.singular}_includes"
end
model_orders() click to toggle source
# File lib/standard_api.rb, line 80
def model_orders
  self.send "#{model.model_name.singular}_orders"
end
model_params() click to toggle source
# File lib/standard_api.rb, line 72
def model_params
  params.require(model.model_name.singular).permit(self.send("#{model.model_name.singular}_params"))
end
normalized_order(orderings) click to toggle source
# File lib/standard_api.rb, line 98
def normalized_order(orderings)
  return nil if orderings.nil?

  orderings = Array(orderings)

  orderings.map! do |order|
    if order.is_a?(Symbol) || order.is_a?(String)
      order = order.to_s
      if order.index(".")
        relation, column = order.split('.').map(&:to_sym)
        { relation => [column] }
      else
        order.to_sym
      end
    elsif order.is_a?(Hash)
      normalized_order = {}
      order.each do |key, value|
        key = key.to_s

        if key.index(".")
          relation, column = key.split('.').map(&:to_sym)
          normalized_order[relation] ||= []
          normalized_order[relation] << { column => value }
        elsif value.is_a?(Hash) && value.keys.first.to_s != 'desc' && value.keys.first.to_s != 'asc'
          normalized_order[key.to_sym] ||= []
          normalized_order[key.to_sym] << value
        else
          normalized_order[key.to_sym] = value
        end
      end
      normalized_order
    end
  end

  orderings
end
orders() click to toggle source

TODO: sanitize orders

# File lib/standard_api.rb, line 94
def orders
  normalized_order(params[:order])
end
resources() click to toggle source
# File lib/standard_api.rb, line 84
def resources
  model.filter(params[:where]).where(current_mask[model.table_name])
end