class Sinatra::Rabbit::Collection

Public Class Methods

[](obj_id) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 226
def self.[](obj_id)
  collections.find { |c| c.collection_name == obj_id } || operation(obj_id)
end
action(action_name, opts={}, &block) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 272
def self.action(action_name, opts={}, &block)
  opts.merge!(:http_method => :post) unless opts[:http_method]
  operation(action_name, opts, &block)
end
base_class() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 202
def self.base_class
  @klass
end
base_class=(klass) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 172
def self.base_class=(klass)
  @klass = klass
end
collection(name, opts={}, &block) click to toggle source

Define new collection using the name

opts Define :id used if the collection is a subcollection

# File lib/sinatra/rabbit/base.rb, line 151
def self.collection(name, opts={}, &block)
  return collections.find { |c| c.collection_name == name } if not block_given?
  new_collection = BaseCollection.collection_class(name, self) do |c|
    c.base_class = self.base_class
    c.with_id!(opts.delete(:with_id)) if opts.has_key?(:with_id)
    c.no_member! if opts.has_key?(:no_member)
    c.generate(name, self, &block)
  end
  collections << new_collection
end
collection_name() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 206
def self.collection_name; @collection_name; end
collections() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 213
def self.collections
  @collections ||= []
end
control(*args) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 176
def self.control(*args)
  raise "The 'control' statement must be used only within context of Operation"
end
description(text=nil) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 221
def self.description(text=nil)
  return @description if text.nil?
  @description = text
end
docs_url() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 134
def self.docs_url
  root_path  + 'docs/' + route_for(path)
end
feature(name) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 185
def self.feature(name)
  features.find { |f| f.name == name }
end
features() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 180
def self.features
  return [] unless base_class.respond_to? :features
  base_class.features.select { |f| f.collection == collection_name }
end
features_for(operation_name) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 281
def self.features_for(operation_name)
  features.select { |f| f.operations.map { |o| o.name}.include?(operation_name) }
end
full_path() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 217
def self.full_path
  root_path + route_for(path)
end
generate(name, parent_collection=nil, &block) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 110
def self.generate(name, parent_collection=nil, &block)
  @collection_name = name.to_sym
  @parent_collection = parent_collection
  class_eval(&block)
  generate_head_route unless Rabbit.disabled? :head_routes
  generate_options_route unless Rabbit.disabled? :options_routes
  generate_docs_route unless Rabbit.disabled? :docs
  self
end
generate_docs_route() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 138
def self.generate_docs_route
  collection = self
  base_class.get docs_url do
    css_file = File.read(File.join(File.dirname(__FILE__), '..', 'docs', 'bootstrap.min.css'))
    collection_file = File.read(File.join(File.dirname(__FILE__), '..', 'docs', 'collection.haml'))
    haml collection_file, :locals => { :collection => collection, :css => css_file }
  end
end
generate_head_route() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 128
def self.generate_head_route
  base_class.head full_path do
    status 200
  end
end
generate_options_route() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 120
def self.generate_options_route
  methods = (['OPTIONS'] + operations.map { |o| o.http_method.to_s.upcase }).uniq.join(',')
  base_class.options full_path do
    headers 'Allow' => methods
    status 200
  end
end
no_member!() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 193
def self.no_member!
  @no_member = true
end
operation(operation_name, opts={}, &block) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 230
def self.operation(operation_name, opts={}, &block)
  # Return operation when no block is given
  return operations.find { |o| o.operation_name == operation_name } unless block_given?

  # Check if current operation is not already registred
  if operation_registred?(operation_name)
    raise "Operation #{operation_name} already registered in #{self.name} collection"
  end

  # Create operation class
  new_operation = operation_class(self, operation_name).generate(self, operation_name, opts, &block)
  operations << new_operation

  # Add route conditions if defined
  if opts.has_key? :if
    base_class.send(:set, :if_true) do |value|
      condition do
        (value.kind_of?(Proc) ? value.call : value) == true
      end
    end
    opts[:if_true] = opts.delete(:if)
  end

  # Make the full_path method on operation return currect operation path
  new_operation.route = root_path + route_for(path, operation_name, :id_name => @with_id || ':id')

  # Change the HTTP method to POST automatically for 'action' operations
  new_operation.http_method = opts.delete(:http_method) if opts[:http_method]

  # Remove :with_capability from Sinatra route options
  route_options = opts.clone
  route_options.delete :with_capability

  # Define Sinatra route and generate OPTIONS route if enabled
  base_class.send(new_operation.http_method || http_method_for(operation_name), new_operation.full_path, route_options, &new_operation.control)

  new_operation.generate_options_route(root_path + route_for(path, operation_name, :no_id_and_member)) unless Rabbit.disabled?(:options_routes)
  new_operation.generate_head_route(root_path + route_for(path, operation_name, :member)) unless Rabbit.disabled?(:head_routes)
  new_operation.generate_docs_route(new_operation.docs_url) unless Rabbit.disabled?(:doc_routes)
  self
end
operations() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 277
def self.operations
  @operations ||= []
end
parent_collection() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 207
def self.parent_collection; @parent_collection; end
parent_routes() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 162
def self.parent_routes
  return '' if @parent_collection.nil?
  route = [ @parent_collection.collection_name.to_s ]
  current_parent = @parent_collection
  while current_parent = current_parent.parent_collection
    route << current_parent.collection_name
  end
  route.reverse.join('/')+'/'
end
path() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 197
def self.path
  with_id_param = @with_id.nil? ? '' : ':id' + (@no_member ? '' : '/')
  parent_routes + with_id_param + ((@no_member) ? '' :  collection_name.to_s)
end
subcollection?() click to toggle source
# File lib/sinatra/rabbit/base.rb, line 209
def self.subcollection?
  !parent_collection.nil?
end
with_id!(id) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 189
def self.with_id!(id)
  @with_id = ":#{id}"
end

Private Class Methods

operation_class(collection_klass, operation_name) click to toggle source

Create an unique class name for all operations within Collection class

# File lib/sinatra/rabbit/base.rb, line 419
def self.operation_class(collection_klass, operation_name)
  begin
    collection_klass.const_get(operation_name.to_s.camelize + 'Operation')
  rescue NameError
    collection_klass.const_set(operation_name.to_s.camelize + 'Operation', Class.new(Operation))
  end
end
operation_registred?(name) click to toggle source
# File lib/sinatra/rabbit/base.rb, line 414
def self.operation_registred?(name)
  operations.any? { |o| o.name == name }
end