module Cerulean::ClassMethods

Public Instance Methods

declared() click to toggle source
# File lib/cerulean.rb, line 76
def declared()
  @declared ||= {} #Hashie::Mash.new(params)
end
delete(name, &block) click to toggle source
# File lib/cerulean.rb, line 64
def delete(name, &block)
  endpoint(name, &block)
end
endpoint(name, &block) click to toggle source
# File lib/cerulean.rb, line 68
def endpoint(name, &block)
  self.class_variable_set(:@@meta, {}) unless self.class_variable_defined?(:@@meta)

  ActionDSL.new(self, name: name, &block)

  self.class_exec do
    require 'boolean'

    def declared()
      @declared ||= {} #Hashie::Mash.new(params)
    end

    def render_presenter(object, **opts)
      if object.is_a?(Array) || object.is_a?(ActiveRecord::Relation)
        if opts.any?
          object.map { |el| meta[:presenter].new(el).as_json(**opts) }
        else
          object.map { |el| meta[:presenter].new(el).as_json() }
        end
      else
        if opts.any?
          meta[:presenter].new(object).as_json(**opts)
        else
          meta[:presenter].new(object).as_json()
        end
      end
    end

    def present(object, **opts)
      render json: render_presenter(object, **opts)
    end

    def meta
      @meta ||= self.class.class_variable_get(:@@meta)[action_name.to_sym]
    end

    def validate_param_type(val, type)
      if val.is_a?(Array)
        parsed = val.map { |el| validate_param_type(el, type[0]) }
        parsed.all? { |el| !el.nil? } ? parsed : nil
      else
        if type == String
          val
        elsif type == Boolean
          if val.blank? || val.downcase == 'null'
            nil
          elsif val.downcase == 'true'
            true
          else
            false
          end
        elsif type == Date
          Date.parse(val) rescue nil
        elsif type == DateTime
          DateTime.parse(val) rescue nil
        else
          Kernel.send(type.to_s, val) rescue nil
        end
      end
    end

    before_action do
      if meta.has_key?(:form)
        p = params
        p = p.permit! if params.respond_to?(:permit!)

        if meta[:form].has_key?(:key) && meta[:form][:key]
          p = params[meta[:form][:key]]
        end

        p = p&.to_hash&.deep_symbolize_keys

        @form = meta[:form][:klass].new(p)
      end

      if meta.has_key?(:params)
        @declared = {}
        errors = {}
        meta[:params].each do |param, opts|
          if params.has_key?(param.to_s)
            p = validate_param_type(params[param.to_s], opts[:type])

            if p.nil? && opts[:null] != true
              errors[param] ||= []
              errors[param] << "#{param.to_s} is not a #{opts[:type].to_s.downcase}"
            else
              if opts.has_key?(:min) || opts.has_key?(:max)
                unless (Float(p) rescue false)
                  errors[param] ||= []
                  errors[param] << "must be a number"
                end
              end

              if opts.has_key?(:min)
                if p < opts[:min]
                  errors[param] ||= []
                  errors[param] << "must be greater than or equal to #{opts[:min]}"
                end
              end

              if opts.has_key?(:max)
                if p > opts[:max]
                  errors[param] ||= []
                  errors[param] << "must be less than or equal to #{opts[:max]}"
                end
              end

              if opts.has_key?(:values)
                unless opts[:values].map { |val| val.to_s }.include?(p.to_s)
                  errors[param] ||= []
                  errors[param] << "must be one of #{opts[:values]}"
                end
              end
            end

            @declared[param] = p
          else
            @declared[param] = opts[:default] if opts.has_key?(:default)
            if opts[:required]
              errors[param] ||= []
              errors[param] << "is required"
            end
          end
        end
        raise ParamsInvalid.new(errors) if errors.keys.any?
      end
    end
  end
end
get(name, &block) click to toggle source
# File lib/cerulean.rb, line 52
def get(name, &block)
  endpoint(name, &block)
end
meta() click to toggle source
# File lib/cerulean.rb, line 100
def meta
  @meta ||= self.class.class_variable_get(:@@meta)[action_name.to_sym]
end
post(name, &block) click to toggle source
# File lib/cerulean.rb, line 56
def post(name, &block)
  endpoint(name, &block)
end
present(object, **opts) click to toggle source
# File lib/cerulean.rb, line 96
def present(object, **opts)
  render json: render_presenter(object, **opts)
end
put(name, &block) click to toggle source
# File lib/cerulean.rb, line 60
def put(name, &block)
  endpoint(name, &block)
end
render_presenter(object, **opts) click to toggle source
# File lib/cerulean.rb, line 80
def render_presenter(object, **opts)
  if object.is_a?(Array) || object.is_a?(ActiveRecord::Relation)
    if opts.any?
      object.map { |el| meta[:presenter].new(el).as_json(**opts) }
    else
      object.map { |el| meta[:presenter].new(el).as_json() }
    end
  else
    if opts.any?
      meta[:presenter].new(object).as_json(**opts)
    else
      meta[:presenter].new(object).as_json()
    end
  end
end
validate_param_type(val, type) click to toggle source
# File lib/cerulean.rb, line 104
def validate_param_type(val, type)
  if val.is_a?(Array)
    parsed = val.map { |el| validate_param_type(el, type[0]) }
    parsed.all? { |el| !el.nil? } ? parsed : nil
  else
    if type == String
      val
    elsif type == Boolean
      if val.blank? || val.downcase == 'null'
        nil
      elsif val.downcase == 'true'
        true
      else
        false
      end
    elsif type == Date
      Date.parse(val) rescue nil
    elsif type == DateTime
      DateTime.parse(val) rescue nil
    else
      Kernel.send(type.to_s, val) rescue nil
    end
  end
end