Module: Innate::SingletonMethods

Included in:
Innate
Defined in:
lib/innate.rb,
lib/innate/node.rb,
lib/innate/route.rb,
lib/innate/state.rb,
lib/innate/dynamap.rb

Overview

script_name, path_info = env, env answer = app.call(env) env.merge!(‘SCRIPT_NAME’ => script_name, ‘PATH_INFO’ => path_info) answer

Constant Summary collapse

PROXY_OPTIONS =
{ :port => 'adapter.port', :host => 'adapter.host',
:adapter => 'adapter.handler' }

Instance Method Summary collapse

Instance Method Details

#at(location) ⇒ Object

Answer with object at location.

Examples:


class Hello
  include Innate::Node
  map '/'
end

Innate.at('/') # => Hello


78
79
80
# File 'lib/innate/dynamap.rb', line 78

def at(location)
  DynaMap.at(location)
end

#call(env, mode = ) ⇒ Array

Treat Innate like a rack application, pass the rack env and optionally the mode the application runs in.

Parameters:

  • env (Hash)

    rack env

  • mode (Symbol) (defaults to: )

    indicates the mode of the application

Returns:

  • (Array)

    with [body, header, status]

Author:

  • manveru



159
160
161
# File 'lib/innate.rb', line 159

def call(env, mode = options[:mode])
  middleware(mode).call(env)
end

#deferObject



17
18
19
20
21
22
23
24
# File 'lib/innate/state.rb', line 17

def defer
  outer = ::Thread.current
  ::Thread.new{
    inner = ::Thread.current
    outer.keys.each{|k| inner[k] = outer[k] }
    yield
  }
end

#go_figure_root(backtrace, options) ⇒ Object

Either setting will surpress the warning that might show up on startup and tells you it couldn’t find an explicit root.

In case these options are not passed we will try to figure out a file named ‘start.rb` in the process’ working directory and assume it’s a valid point.

Examples:

Innate can be started by:


Innate.start :file => __FILE__
Innate.start :root => File.dirname(__FILE__)


185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/innate.rb', line 185

def go_figure_root(backtrace, options)
  if root = options[:root]
    root
  elsif file = options[:file]
    File.dirname(file)
  elsif File.file?('start.rb')
    Dir.pwd
  else
    root = File.dirname(backtrace[0][/^(.*?):\d+/, 1])
    Log.warn "No explicit root folder found, assuming it is #{root}"
    root
  end
end

#map(location, object = nil, &block) ⇒ Object

Maps the given object or block to location, object must respond to #call in order to be of any use.

Examples:

with passed object


Innate.map('/', lambda{|env| [200, {}, "Hello, World"] })
Innate.at('/').call({}) # => [200, {}, "Hello, World"]

with passed block


Innate.map('/'){|env| [200, {}, ['Hello, World!']] }
Innate.at('/').call({})


64
65
66
# File 'lib/innate/dynamap.rb', line 64

def map(location, object = nil, &block)
  DynaMap.map(location, object || block)
end

#middleware(mode = , &block) ⇒ Object



163
164
165
# File 'lib/innate.rb', line 163

def middleware(mode = options[:mode], &block)
  options[:middleware_compiler].build(mode, &block)
end

#middleware!(mode = , &block) ⇒ Object



167
168
169
# File 'lib/innate.rb', line 167

def middleware!(mode = options[:mode], &block)
  options[:middleware_compiler].build!(mode, &block)
end

#middleware_recompile(mode = ) ⇒ Object



171
172
173
# File 'lib/innate.rb', line 171

def middleware_recompile(mode = options[:mode])
  options[:middleware_compiler]::COMPILED[mode].compile!
end

#node(location, node = nil) ⇒ Class, Module

Convenience method to include the Node module into node and map to a location.

Parameters:

  • location (#to_s)

    where the node is mapped to

  • node (Node, nil) (defaults to: nil)

    the class that will be a node, will try to look it up if not given

Returns:

  • (Class, Module)

    the node argument or detected class will be returned

See Also:

  • SingletonMethods::node_from_backtrace

Author:

  • manveru



999
1000
1001
1002
1003
1004
# File 'lib/innate/node.rb', line 999

def node(location, node = nil)
  node ||= node_from_backtrace(caller)
  node.__send__(:include, Node)
  node.map(location)
  node
end

#node_from_backtrace(backtrace) ⇒ Class, Module

Cheap hack that works reasonably well to avoid passing self all the time to Innate::node We simply search the file that Innate::node was called in for the first class definition above the line that Innate::node was called and look up the constant. If there are any problems with this (filenames containing ‘:’ or metaprogramming) just pass the node parameter explicitly to Innate::node

Parameters:

  • backtrace (Array<String>, #[])

Returns:

  • (Class, Module)

See Also:

  • SingletonMethods::node

Author:

  • manveru



1021
1022
1023
1024
1025
1026
# File 'lib/innate/node.rb', line 1021

def node_from_backtrace(backtrace)
  filename, lineno = backtrace[0].split(':', 2)
  regexp = /^\s*class\s+(\S+)/
  File.readlines(filename)[0..lineno.to_i].reverse.find{|l| l =~ regexp }
  const_get($1)
end

#Rewrite(key, value = nil, &block) ⇒ Object



110
111
112
# File 'lib/innate/route.rb', line 110

def Rewrite(key, value = nil, &block)
  Rewrite[key] = value || block
end

#Route(key, value = nil, &block) ⇒ Object



106
107
108
# File 'lib/innate/route.rb', line 106

def Route(key, value = nil, &block)
  Route[key] = value || block
end

#setup_dependenciesObject



143
144
145
# File 'lib/innate.rb', line 143

def setup_dependencies
  options[:setup].each{|obj| obj.setup if obj.respond_to?(:setup) }
end

#start(given_options = {}, &block) {|MiddlewareCompiler| ... } ⇒ nil

The method that starts the whole business.

Call Innate.start after you defined your application.

Usually, this is a blocking call and will not return until the adapter has finished, which usually happens when you kill the application or hit ^C.

We do return if options.started is true, which indicates that all you wanted to do is setup the environment and update options.

Examples:

usage


# passing options
Innate.start :adapter => :mongrel, :mode => :live

# defining custom middleware
Innate.start do |m|
  m.innate
end

Parameters:

  • block (Proc)

    will be passed to #middleware!

  • param (Hash)

    a customizable set of options

Yields:

Returns:

  • (nil)

    if options.started is true



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/innate.rb', line 105

def start(given_options = {}, &block)
  root = given_options.delete(:root)
  file = given_options.delete(:file)

  found_root = go_figure_root(caller, :root => root, :file => file)
  Innate.options.roots = [*found_root] if found_root

  # Convert some top-level option keys to the internal ones that we use.
  PROXY_OPTIONS.each{|k,v| given_options[v] = given_options.delete(k) }
  given_options.delete_if{|k,v| v.nil? }

  # Merge the user's given options into our existing set, which contains defaults.
  options.merge!(given_options)

  setup_dependencies
  middleware!(options.mode, &block) if block_given?

  return if options.started
  options.started = true

  signal = options.trap
  trap(signal){ stop(10) } if signal

  start!
end

#start!(mode = ) ⇒ Object



131
132
133
# File 'lib/innate.rb', line 131

def start!(mode = options[:mode])
  Adapter.start(middleware(mode))
end

#stop(wait = 3) ⇒ Object



135
136
137
138
139
140
141
# File 'lib/innate.rb', line 135

def stop(wait = 3)
  Log.info("Shutdown within #{wait} seconds")
  Timeout.timeout(wait){ teardown_dependencies }
  Timeout.timeout(wait){ exit }
ensure
  exit!
end

#sync(&block) ⇒ Object

Use this method to achieve thread-safety for sensitive operations.

This should be of most use when manipulating files to prevent other threads from doing the same, no other code will be scheduled during execution of this method.

Parameters:

  • block (Proc)

    the things you want to execute

See Also:

  • State::Fiber#sync


13
14
15
# File 'lib/innate/state.rb', line 13

def sync(&block)
  Thread.exclusive(&block)
end

#teardown_dependenciesObject



147
148
149
# File 'lib/innate.rb', line 147

def teardown_dependencies
  options[:setup].each{|obj| obj.teardown if obj.respond_to?(:teardown) }
end

#to(object) ⇒ Object

Returns one of the paths the given object is mapped to.

Examples:


class Hello
  include Innate::Node
  map '/'
end

Innate.to(Hello) # => '/'


92
93
94
# File 'lib/innate/dynamap.rb', line 92

def to(object)
  DynaMap.to(object)
end