Module: Camping

Defined in:
lib/camping/tools.rb,
lib/camping.rb,
lib/camping/ar.rb,
lib/camping/loader.rb,
lib/camping/server.rb,
lib/camping/session.rb,
lib/camping/version.rb,
lib/camping/commands.rb,
lib/camping-unabridged.rb,
lib/camping/gear/firewatch.rb

Overview

Firewatch is Camping’s logger. It wraps Rack::CommonLogger, and gives a mechanism to Redirect logs.

Defined Under Namespace

Modules: Base, CommandsHelpers, Controllers, Helpers, Models, Session, Tools, Views Classes: Commands, Cookies, Firewatch, Generators, H, Loader, Server

Constant Summary collapse

C =
self
S =
IO.read(__FILE__) rescue nil
P =
"<h1>Cam\ping Problem!</h1><h2>%s</h2>"
U =
Rack::Utils
Apps =

Our array of Apps

[]
SK =

Key for r.session

"camping"
G =

Our array of Gear

[]
O =

Our Hash of Options

H.new
X =
Controllers
Reloader =
Loader
VERSION =
"3.2.5"

Class Method Summary collapse

Class Method Details

.call(e) ⇒ Array

Ruby web servers use this method to enter the Camping realm. The e argument is the environment variables hash as per the Rack specification. Array with [status, headers, body] is expected at the output.

See: github.com/rack/rack/blob/main/SPEC.rdoc

Parameters:

  • A (Array)

    rack response

Returns:

  • (Array)

    A rack response



728
729
# File 'lib/camping-unabridged.rb', line 728

def call e;k,m,*a=X.D e["PATH_INFO"],e['REQUEST_METHOD'].
downcase,e;k.new(e,m,prx).service(*a).to_a;rescue;r500(:I,k,m,$!,:env=>e).to_a end

.gearObject

Helper method to list gear



854
# File 'lib/camping-unabridged.rb', line 854

def gear;G end

.goes(m, g = TOPLEVEL_BINDING) ⇒ Object

When you are running multiple applications, you may want to create independent modules for each Camping application. Camping::goes defines a top level constant with the whole MVC rack inside:

require 'camping'
Camping.goes :Nuts

module Nuts::Controllers; ... end
module Nuts::Models;      ... end
module Nuts::Views;       ... end

Additionally, you can pass a Binding as the second parameter, which enables you to create a Camping-based application within another module.

Here’s an example of name spacing your web interface and code for a worker process together:

module YourApplication
  Camping.goes :Web, binding()
  module Web
    ...
  end
  module Worker
    ...
  end
end

All the applications will be available in Camping::Apps.

Camping offers a shortcut for adding thin files, and templates to your apps. Add them at the end of the same ruby file that you call ‘Camping.goes`:

require 'camping'
Camping.goes :Nuts

module Nuts::Controllers; ... end
module Nuts::Models;      ... end
module Nuts::Views;       ... end

__END__

@@ /style.css
* { margin: 0; padding: 0 }

@@ /test.foo
<H1>Hello friends! Nice to meet you.<H1>

@@ index.erb
Hello <%= @world %>

Also sets the apps Meta Data. Can be found at O

@app: String - The app in question @parent: String - @root: String - @line_number: Int - The line number that the app was declared @file: String - The file location for this



931
932
933
934
935
936
# File 'lib/camping-unabridged.rb', line 931

def goes m,g=TOPLEVEL_BINDING;sp=caller[0].split('`')[0].split(":");fl,ln=
sp[0]+' <Cam\ping App> ',sp[1].to_i;Apps<< a=eval(S.gsub(/Camping/,m.to_s),g,fl,1);caller[0]=~/:/
IO.read(a.set:__FILE__,$`)=~/^__END__/&&(b=$'.split(/^@@\s*(.+?)\s*\r?\n/m)
).shift rescue nil;a.set :_t,H[*b||[]]
a.set :_meta, H[file: fl, line_number: ln, parent: self,
root: (name != "Cam\ping" ? '/' + CampTools.to_snake(name) : '/')];C.configure(a)end

.make_campObject

Create method to setup routes for Camping upon reload.



697
# File 'lib/camping-unabridged.rb', line 697

def make_camp;X.M prx;Apps.map(&:make_camp) end

.method_missing(m, c, *a) ⇒ Object

The Camping scriptable dispatcher. Any unhandled method call to the app module will be sent to a controller class, specified as an argument.

Blog.get(:Index)
#=> #<Blog::Controllers::Index ... >

The controller object contains all the @cookies, @body, @headers, etc. formulated by the response.

You can also feed environment variables and query variables as a hash, the final argument.

Blog.post(:Login, :input => {'username' => 'admin', 'password' => 'camping'})
#=> #<Blog::Controllers::Login @user=... >

Blog.get(:Info, :env => {'HTTP_HOST' => 'wagon'})
#=> #<Blog::Controllers::Info @headers={'HTTP_HOST'=>'wagon'} ...>


753
754
755
# File 'lib/camping-unabridged.rb', line 753

def method_missing m,c,*a;h=Hash===a[-1]?a.pop : {};e=H[Rack::MockRequest.
env_for('',h.delete(:env)||{})];k=X.const_get(c).new(e,m.to_s,prx);h.each{|i,v|
k.send"#{i}=",v};k.service(*a)end

.optionsObject

A hash where you can set different settings.



859
# File 'lib/camping-unabridged.rb', line 859

def options;O;end

.pack(*a, &b) ⇒ Object

Add gear to your app:

module Blog
  pack Camping::Gear::CSRF
end

Why have plugins in the first place if we can just include and extend our modules and classes directly? To perform setup actions!

Sometimes you might have ClassMethods that you want to modify Camping with, This gives us a way to do that. In your gear:

module MyGear
  module ClassMethods
    # Define Class Methods here
  end
  def self.included(mod)
    mod.extend(ClassMethods)
  end
end

Optionally a plugin may have a setup method and a ClassMethods module:

module MyGear
  def self.setup(s)
    # Perform setup actions
  end
  module ClassMethods
    # Define Class Methods here
  end
end

Camping gear can also provide Helper methods to our controllers:

module MyGear
  module HelperMethods
    # Define Helper Methods here
  end

  # This is plumbing in our Gear to add our Helper methods.
  class << self
    def included(mod)
      mod::Helpers.include(HelperMethods)
    end
  end
end

Helper methods are available in our controllers.



847
# File 'lib/camping-unabridged.rb', line 847

def pack*a,&b;G<< g=a.shift;include g;g.setup(self,*a,&b)end

.prxString

An internal method used to return the current app’s url_prefix. the prefix is processed to make sure that it’s not all wonky. excessive trailing and leading slashes are removed. A trailing slash is added.

Returns:

  • (String)

    A reference to the URL response



717
# File 'lib/camping-unabridged.rb', line 717

def prx;@_prx||=CampTools.normalize_slashes(O[:url_prefix])end

.routesObject

Helper method for getting routes from the controllers. helps Camping::Server map routes to multiple apps. Usage:

Nuts.routes # returns routes for Nuts
Camping.routes


709
# File 'lib/camping-unabridged.rb', line 709

def routes;(Apps.map(&:routes)<<X.v).flatten end

.set(k, v) ⇒ Object

Shortcut for setting options:

module Blog
  set :secret, "Hello!"
end


868
# File 'lib/camping-unabridged.rb', line 868

def set k,v;O[k]=v end

.use(*a, &b) ⇒ Object

Injects a middleware:

module Blog
  use Rack::MethodOverride
  use Rack::Session::Memcache, :key => "session"
end

This piece of code feels a bit confusing, but let’s walk through it. Rack apps all implement a Call method. This is how Ruby web servers call the app, or code that you’ve set up. In our case, our camping apps.

The Use method is setting up a new middleware, it shifts the first argument supplied to Use, which should be the Middleware name, then initializes it. That’s your new middleware. Rack based middleware accept a single argument to their initialize methods, which is an app. Optionally settings and a block are supplied.

So a new app is made, and its settings are supplied, then immediately sent to the new middleware we just added. But the cool part is where we call meta_def. meta_def takes a symbol and a block, and defines a class method into the current context. Our current context is our camping app. So when we call it below we’re redefining the call method to call the new middleware that we just added. The ‘m` variable below represents our newly created middleware object, that we initialized with our old app. and because we’re defining a new call method with a block, it’s captured in that block.

This creates a sequence of middleware that isn’t recorded anywhere, but nonetheless is set up in the proper order and called in the proper order.



793
# File 'lib/camping-unabridged.rb', line 793

def use*a,&b;m=a.shift.new(method(:call),*a,&b);meta_def(:call){|e|m.call(e)};m;end

.versionObject



3
4
5
# File 'lib/camping/version.rb', line 3

def self.version
  VERSION
end