class Roda::RodaPlugins::RestApi::Resource

Constants

FORM_HASH
FORM_INPUT
OPTIONS
POST_BODY

Attributes

captures[RW]
id_pattern[R]
parent[R]
path[R]
request[R]
singleton[R]

Public Class Methods

new(path, request, parent, option_chain=[]) click to toggle source
# File lib/roda/plugins/rest_api.rb, line 45
def initialize(path, request, parent, option_chain=[])
  @request = request
  @path = path.to_s
  traverse_options option_chain
  if parent
    @parent = parent
    @path = ":id/#{@path}" unless @bare
  end
end

Public Instance Methods

content_type() click to toggle source
# File lib/roda/plugins/rest_api.rb, line 62
def content_type
  if @serializer && @serializer.respond_to?(:content_type)
    @serializer.content_type
  else
    @content_type
  end
end
opts() click to toggle source
# File lib/roda/plugins/rest_api.rb, line 70
def opts
  @resource || {}
end
perform(method, id = nil) click to toggle source
# File lib/roda/plugins/rest_api.rb, line 104
def perform(method, id = nil)
  begin
    args = self.arguments(method, id)
    perform_wrapped(method, args) do |args|
      r = self.send(method).call(args)
    end
  rescue StandardError => e
    raise if ENV['RACK_ENV'] == 'development'
    @request.response.status = method === :save ? 422 : 404
    @request.response.write e
  end
end
perform_wrapped(method, args, &blk) click to toggle source
# File lib/roda/plugins/rest_api.rb, line 96
def perform_wrapped(method, args, &blk)
  if respond_to? :"around_#{method}"
    send :"around_#{method}", args, &blk
  else
    blk.call(args)
  end
end
permit(*permitted) click to toggle source
# File lib/roda/plugins/rest_api.rb, line 80
def permit(*permitted)
  @permitted = permitted
end
routes(*routes) { || ... } click to toggle source
# File lib/roda/plugins/rest_api.rb, line 74
def routes(*routes)
  routes! if @routes
  yield if block_given?
  @routes = routes
end
routes!() click to toggle source
# File lib/roda/plugins/rest_api.rb, line 84
def routes!
  unless @routes
    @routes = SINGLETON_ROUTES.dup
    @routes << :index unless @singleton
  end
  @routes.each { |route| @request.send(route) }
end

Protected Instance Methods

arguments(method, id) click to toggle source
# File lib/roda/plugins/rest_api.rb, line 119
def arguments(method, id)
  args = if method === :save
    form = Rack::Request::FORM_DATA_MEDIA_TYPES.include?(@request.media_type)
    permitted_args(form ? @request.POST : JSON.parse(@request.body.read))
  else
    symbolize_keys @request.GET
  end
  args.merge!(@primary_key.to_sym => id) if id
  args.merge!(@parent_key.to_sym => @captures[0]) if @captures
  args
end

Private Instance Methods

permitted?(keypath) click to toggle source
# File lib/roda/plugins/rest_api.rb, line 180
def permitted?(keypath)
  return false unless @permitted
  permitted = @permitted
  find_key = ->(items, key){
    items.find do |item|
      case item
      when Hash
        !!item.keys.index(key)
      when Symbol
        item === key
      end
    end
  }
  keypath.each do |key|
    found = find_key.call(permitted, key)
    permitted = found.is_a?(Hash) ? found.values.flatten : []
    return false unless found
  end
end
permitted_args(args, keypath = []) click to toggle source
# File lib/roda/plugins/rest_api.rb, line 161
def permitted_args(args, keypath = [])
  permitted = nil
  case args
  when Hash
    permitted = Hash.new
    args.each_pair do |k,v|
      keypath << k.to_sym
      if permitted?(keypath)
        value = permitted_args(v, keypath)
        permitted[k.to_sym] = value if value
      end
      keypath.pop
    end
  else
    permitted = args if permitted?(keypath)
  end
  permitted
end
symbolize_keys(args) click to toggle source
# File lib/roda/plugins/rest_api.rb, line 152
def symbolize_keys(args)
  _args = {}
  args.each do |k,v|
    v = symbolize_keys(v) if v.is_a?(Hash)
    _args[k.to_sym] = v
  end
  _args
end
traverse_options(option_chain) click to toggle source
# File lib/roda/plugins/rest_api.rb, line 133
def traverse_options(option_chain)
  reverse_chain = option_chain.reverse
  OPTIONS.each_pair do |key, default|
    ivar = "@#{key}"
    options = reverse_chain.find do |opts|
      opts[key]
    end
    self.instance_variable_set(ivar, (options && options[key]) || default)
  end
  if @wrapper
    raise ":wrapper should be a module" unless @wrapper.is_a? Module
    self.extend @wrapper
  end
  if @serializer
    raise ":serializer should respond to :serialize" unless @serializer.respond_to?(:serialize)
    @serialize = ->(res){@serializer.serialize(res)}
  end
end