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 Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#appRack::Builder

Returns an instance of ‘Rack::Builder` that can be used to start a Innate application.

Returns:

  • (Rack::Builder)


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

def app
  @app
end

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

    indicates the mode of the application

Returns:

  • (Array)

    with [body, header, status]

Author:

  • manveru



185
186
187
# File 'lib/innate.rb', line 185

def call(env)
  Innate.app.call(env)
end

#coreRack::Cascade

Returns an instance of ‘Rack::Cascade` for running Innate applications. This method should be called using `Rack::Builder#run`:

Innate.middleware(:dev) do
  run Innate.core
end

Returns:

  • (Rack::Cascade)


212
213
214
215
216
217
218
219
220
# File 'lib/innate.rb', line 212

def core
  roots, publics = options[:roots], options[:publics]

  joined  = roots.map { |root| publics.map { |p| File.join(root, p) } }
  joined  = joined.flatten.map { |p| Rack::File.new(p) }
  current = Current.new(Route.new(DynaMap), Rewrite.new(DynaMap))

  return Rack::Cascade.new(joined << current, [404, 405])
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__)


254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/innate.rb', line 254

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

Sets the middleware for the given mode.

Examples:

Innate.middleware(:dev) do
  use Rack::Head
  use Rack::Reloader

  run Innate.core
end

Parameters:

  • mode (#to_sym)

    The mode that the middleware belong to.

  • block (Proc)

    Block containing the middleware. This block will be passed to an instance of ‘Rack::Builder` and can thus contain everything this class allows you to use.



238
239
240
241
242
# File 'lib/innate.rb', line 238

def middleware(mode, &block)
  MIDDLEWARE[mode.to_sym] = block

  recompile_middleware(mode)
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



1076
1077
1078
1079
1080
1081
# File 'lib/innate/node.rb', line 1076

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



1098
1099
1100
1101
1102
1103
# File 'lib/innate/node.rb', line 1098

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

#recompile_middleware(mode = ) ⇒ Object

Updates ‘Innate.app` based on the current mode.

Parameters:

  • mode (#to_sym) (defaults to: )

    The mode to use.



194
195
196
197
198
199
200
# File 'lib/innate.rb', line 194

def recompile_middleware(mode = options[:mode])
  mode = mode.to_sym

  if MIDDLEWARE[mode] and options[:mode] == mode
    Innate.app = Rack::Builder.new(&MIDDLEWARE[mode]).to_app
  end
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

#setupObject



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

def setup
  options.mode ||= (ENV['RACK_ENV'] || :dev)
end

#setup_dependenciesObject



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

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

#start(options = {}) ⇒ 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

Parameters:

  • param (Hash)

    a customizable set of options

Returns:

  • (nil)

    if options.started is true



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/innate.rb', line 113

def start(options = {})
  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

  return if innate_options.started

  innate_options.started = true

  signal = innate_options.trap

  trap(signal){ stop(10) } if signal

  mode = self.options[:mode].to_sym

  # While Rack itself will spit out errors for invalid instances of
  # Rack::Builder these errors are typically not very user friendly.
  if !Innate.app or !MIDDLEWARE[mode]
    raise(
      ArgumentError,
      "The mode \"#{mode}\" does not have a set of middleware defined. " \
        "You can define these middleware using " \
        "#{self}.middleware(:#{mode}) { ... }"
    )
  end

  start!
end

#start!(mode = ) ⇒ Object



153
154
155
# File 'lib/innate.rb', line 153

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

#stop(wait = 3) ⇒ Object



157
158
159
160
161
162
163
# File 'lib/innate.rb', line 157

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



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

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