Class: Pancake::Stack

Inherits:
Object show all
Extended by:
Hooks::OnInherit, Middleware, Paths
Defined in:
lib/pancake/stack/stack.rb,
lib/pancake/stack/router.rb,
lib/pancake/stack/configuration.rb

Defined Under Namespace

Classes: Configuration, Router

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Hooks::OnInherit

extended, inherited, on_inherit

Methods included from Middleware

build, extended, middlewares, stack, use

Methods included from Paths

dirs_and_glob_for, dirs_for, extended, paths_for, push_paths, unique_paths_for

Constructor Details

#initialize(app = nil, opts = {}) {|self.configuration(@app_name)| ... } ⇒ Stack

Returns a new instance of Stack.

Yields:



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/pancake/stack/stack.rb', line 81

def initialize(app = nil, opts = {})
  @app_name = opts.delete(:app_name) || self.class

  master = opts.delete(:master)
  self.class.initialize_stack(:master => master) unless self.class.initialized?
  self.class.set_as_master! if master
  Pancake.configuration.stacks[@app_name] = self

  # setup the configuration for this stack
  Pancake.configuration.configs[@app_name] = opts[:config] if opts[:config]
  self.configuration(@app_name)
  yield self.configuration(@app_name) if block_given?

  @app ||= self.class.new_endpoint_instance

  self.class.before_build_stack.each{|b| b.call(self, @app_name, opts)}

  mwares = self.class.middlewares

  @stack = Pancake::Middleware.build(@app, mwares)
  app_config = Pancake.configuration.configs(@app_name)
  app_config.stack = self.class
  app_config.router.configuration = app_config
  router = Pancake.configuration.configs[@app_name].router
  router.mount_applications!
  router.default(@stack)
  self.class.after_build_stack.each{ |blk| blk.call(self, @app_name, opts) }
end

Instance Attribute Details

#app_nameObject

Returns the value of attribute app_name.



3
4
5
# File 'lib/pancake/stack/stack.rb', line 3

def app_name
  @app_name
end

Class Method Details

.add_root(*args) ⇒ Object

Adds the file to the stack root.

Examples:

MyStack.add_root(__FILE__) # in a file in the root of the stack

Parameters:

  • file
    • The file identifier



63
64
65
# File 'lib/pancake/stack/stack.rb', line 63

def self.add_root(*args)
  roots << Pancake.get_root(*args)
end

.after_build_stack(&blk) ⇒ Object



48
49
50
51
# File 'lib/pancake/stack/stack.rb', line 48

def self.after_build_stack(&blk)
  _after_build_stack << blk if blk
  _after_build_stack
end

.after_stack_initialize(&blk) ⇒ Object



43
44
45
46
# File 'lib/pancake/stack/stack.rb', line 43

def self.after_stack_initialize(&blk)
  _after_stack_initialize << blk if blk
  _after_stack_initialize
end

.apply_layout(name = nil, &blk) ⇒ Object

Specify a layout to use for this stack and all children stacks Layouts are provided by Wrapt, and Pancake::Stacks::Short will use the layout when directed to by calling this method. Simply call it to activate layouts with the default options, or provide it with options to direct wrapt.

You can specify a layout to use by name, provide it options or provide a block that you can use to set the layout via the environment.

Examples:

# Direct the short stack to use a layout
layout

# Set the layout to a non-default one
layout "non_standard"

# Directly set the layout via the Wrapt::Layout object
layout do |env|
  r = Rack::Request.new(env)
  l = env['layout']
  if r.params['foo'] == 'bar'
    l.template_name = "foo"
  end
end

See Also:

  • Wrapt
  • Wrapt::Layout


223
224
225
226
# File 'lib/pancake/stack/stack.rb', line 223

def self.apply_layout(name = nil, &blk)
  @use_layout = true
  @default_layout = name
end

.base_template_nameObject

Raises:

  • (Errors::NotImplemented)


259
260
261
# File 'lib/pancake/stack/stack.rb', line 259

def self.base_template_name
  raise Errors::NotImplemented, "Stack may not be used for templates until it implements a base_template_name method"
end

.before_build_stack(&blk) ⇒ Object



53
54
55
56
# File 'lib/pancake/stack/stack.rb', line 53

def self.before_build_stack(&blk)
  _before_build_stack << blk if blk
  _before_build_stack
end

.configuration(label = self, &block) ⇒ Object

Provides access to the configuration block for the stack. If a block is provided, it opens the specific configuration instances anonymous class and allows you to edit it. If no block is provided, it just returns the configuration object.

:api: public



14
15
16
17
18
# File 'lib/pancake/stack/configuration.rb', line 14

def self.configuration(label = self, &block)
  config = Pancake.configuration.configs[label] ||= self::Configuration.new
  config.class.class_eval(&block) if block
  config
end

.default_layoutObject



236
237
238
239
240
241
242
# File 'lib/pancake/stack/stack.rb', line 236

def self.default_layout
  if @default_layout
    @default_layout
  else
    @default_layout = superclass.respond_to?(:default_layout) && superclass.default_layout
  end
end

.include_pancake_stack!(include_it = true) ⇒ Object



73
74
75
# File 'lib/pancake/stack/stack.rb', line 73

def self.include_pancake_stack!(include_it = true)
  @include_pancake_stack = include_it
end

.include_pancake_stack?Boolean

Returns:

  • (Boolean)


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

def self.include_pancake_stack?
  !!@include_pancake_stack
end

.initialize_stack(opts = {}) ⇒ Object

Iterates the list of roots in the stack, and initializes the app found their



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/pancake/stack/stack.rb', line 25

def self.initialize_stack(opts = {})
  raise "Stack root not set" if roots.empty?
  master = opts.delete(:master)
  set_as_master! if master

  paths_for(:config     ).each{ |f| require f.join }
  paths_for(:mounts     ).each{ |f| require f.join }
  paths_for(:middleware ).each{ |f| require f.join }

  router.mount_applications!

  set_as_master! if master
  @initialized = true
  # run the hook for after mounting
  after_stack_initialize.each{ |blk| blk.call(self) }
end

.initialized?Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/pancake/stack/stack.rb', line 69

def self.initialized?
  !!@initialized
end

.load_rake_tasks!(opts = {}) ⇒ Object

Loads the rake task for this stack, and all mounted stacks

To have your rake task loaded include a “tasks” director in the stack root

Tasks found in all stack roots are loaded in the order of the stack roots declearations



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/pancake/stack/stack.rb', line 141

def self.load_rake_tasks!(opts={})
  stackup(opts) # load the application
  master = opts.delete(:master) # Don't get the other stacks to boot as master
  opts[:_rake_files_loaded] ||= []
  # For each mounted application, load the rake tasks
  self::Router.mounted_applications.each do |app|
    if app.mounted_app.respond_to?(:load_rake_tasks!)
      app.mounted_app.load_rake_tasks!(opts)
    end
  end
  paths_for(:rake_tasks).each do |f|
    path = File.join(*f)
    unless opts[:_rake_files_loaded].include?(path)
      load path
      opts[:_rake_files_loaded] << path
    end
  end
end

.new_endpoint_instanceObject

get a new instance of the application for this stack Ovewrite this to provide custom application initialization :api: overwritable



130
131
132
# File 'lib/pancake/stack/stack.rb', line 130

def self.new_endpoint_instance
  MISSING_APP
end

.routerObject



6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/pancake/stack/router.rb', line 6

def self.router
  @router ||= begin
    if superclass.respond_to?(:router) && superclass.router
      r = superclass.router.clone(self::Router)
      r.stack = self
    else
      r = self::Router.new
      r.stack = self
    end
    yield r if block_given?
    r
  end
end

.set_as_master!Object

Sets this as a master stack. This means that the “master” directory will be added to all existing stack roots



245
246
247
248
249
250
251
252
253
# File 'lib/pancake/stack/stack.rb', line 245

def self.set_as_master!
  Pancake.master_stack ||= self
  # Want to add master to the roots for this stack only
  roots.dup.each do |root|
    unless root =~ /master\/?$/
      roots << File.join(root, 'master')
    end
  end
end

.stackup(opts = {}, &block) ⇒ Object

Construct a stack using the application, wrapped in the middlewares



112
113
114
115
116
117
118
119
120
# File 'lib/pancake/stack/stack.rb', line 112

def self.stackup(opts = {}, &block)
  app = new(nil, opts, &block)
  r = Pancake.configuration.configs[app.app_name].router
  if include_pancake_stack?
    Pancake.start{r}
  else
    r
  end
end

Symlinks files in the public roots of this stack and all mounted stacks. Provided a mounted application responds to the symlink_public_files! method then it will be called. symlinks public files from all roots of the stacks to Pancake.root/public

Author:

  • Daniel Neighman



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/pancake/stack/stack.rb', line 166

def self.symlink_public_files!
  raise "Pancake root not set" unless Pancake.root

  public_root = File.join(Pancake.root, "public")
  mount_point = configuration.router.base_url

  unique_paths_for(:public).sort_by{|(r,p)| p}.each do |(r,p)|
    # don't try to symlink the symlinks
    origin_path = File.join(r, p)
    next if r == public_root || FileTest.directory?(origin_path)

    output_path = File.join(public_root, mount_point, p)

    unless File.exists?(File.dirname(output_path))
      FileUtils.mkdir_p(File.dirname(output_path))
    end
    # unless the dir exists... create it
    puts "Linking #{output_path}"
    FileUtils.ln_s(origin_path, output_path, :force => true)
  end

  router.mounted_applications.each do |s|
    if s.mounted_app.respond_to?(:symlink_public_files!)
      s.mounted_app.symlink_public_files!
    end
  end
end

.template(name, opts = {}) ⇒ Object

Raises:

  • (Errors::NotImplemented)


255
256
257
# File 'lib/pancake/stack/stack.rb', line 255

def self.template(name,opts ={})
  raise Errors::NotImplemented, "Stack may not be used for templates until it implements a template method"
end

.use_layout?Boolean

Returns:

  • (Boolean)


228
229
230
231
232
233
234
# File 'lib/pancake/stack/stack.rb', line 228

def self.use_layout?
  if @use_layout
    @use_layout
  else
    @use_layout = superclass.respond_to?(:use_layout?) && superclass.use_layout?
  end
end

Instance Method Details

#call(env) ⇒ Object

stackup



122
123
124
# File 'lib/pancake/stack/stack.rb', line 122

def call(env)
  Pancake.configuration.configs[@app_name].router.call(env)
end

#configuration(label = self.class) {|self.class.configuration(label)| ... } ⇒ Object

Yields:



20
21
22
23
# File 'lib/pancake/stack/configuration.rb', line 20

def configuration(label = self.class)
  yield self.class.configuration(label) if block_given?
  self.class.configuration(label)
end