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



161
162
163
# File 'lib/innate.rb', line 161

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

#deferObject



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

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__)


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

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



165
166
167
# File 'lib/innate.rb', line 165

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

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



169
170
171
# File 'lib/innate.rb', line 169

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

#middleware_recompile(mode = ) ⇒ Object



173
174
175
# File 'lib/innate.rb', line 173

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



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

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



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

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{|ln| ln =~ 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



145
146
147
# File 'lib/innate.rb', line 145

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

#start(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



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

def start(options = {}, &block)
  root, file = options.delete(:root), options.delete(:file)
  innate_options = Innate.options

  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{|given, proxy| options[proxy] = options[given] }
  options.delete_if{|key, value| PROXY_OPTIONS[key] || value.nil? }

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

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

  return if innate_options.started
  innate_options.started = true

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

  start!
end

#start!(mode = ) ⇒ Object



133
134
135
# File 'lib/innate.rb', line 133

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

#stop(wait = 3) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/innate.rb', line 137

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



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

def sync(&block)
  SEMAPHORE.synchronize(&block)
end

#teardown_dependenciesObject



149
150
151
# File 'lib/innate.rb', line 149

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