rack-golem 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +84 -0
- data/lib/rack/golem.rb +65 -0
- data/lib/rack_golem.rb +1 -0
- data/rack-golem.gemspec +12 -0
- data/test/spec_golem.rb +95 -0
- metadata +71 -0
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
>Made of consonants and vowels,
|
2
|
+
>there is a terrible Name,
|
3
|
+
>that in its essence encodes God’s all,
|
4
|
+
>power, guarded in letters, in hidden syllables. -- Jorge Luis Borges
|
5
|
+
|
6
|
+
GOLEM
|
7
|
+
=====
|
8
|
+
|
9
|
+
I would describe Golem as a Ramaze for kids.
|
10
|
+
Golem is not a framework though, just a controller, but you know... the kind of controller that leaves you in the train
|
11
|
+
even if you did not buy a ticket.
|
12
|
+
It leaves you on the rails if you will (incredibly good pun intended).
|
13
|
+
|
14
|
+
Install with:
|
15
|
+
|
16
|
+
sudo gem install rack-golem
|
17
|
+
|
18
|
+
Config.ru is one of his names, so say it in a Rackup file.
|
19
|
+
|
20
|
+
require 'db' # Loads ORM models and all
|
21
|
+
require 'go' # Our controller (I don not like that word really)
|
22
|
+
use Rack::ContentLength
|
23
|
+
use Rack::Session::Cookies
|
24
|
+
run Go
|
25
|
+
|
26
|
+
And the winner is:
|
27
|
+
|
28
|
+
require 'rack/golem'
|
29
|
+
|
30
|
+
class Go
|
31
|
+
include Rack::Golem # To hell with sub-classes !!!
|
32
|
+
|
33
|
+
before do
|
34
|
+
# Here you can do many things
|
35
|
+
# In order to help you here are some variables you can read and override:
|
36
|
+
# @r => the Rack::Request object
|
37
|
+
# @res => the Rack::Response object
|
38
|
+
# @action => Name of the public method that will handle the request
|
39
|
+
# @action_arguments => Arguments for the action (really?)
|
40
|
+
end
|
41
|
+
|
42
|
+
def index(*args)
|
43
|
+
# When no public method is found
|
44
|
+
# Of course you don't have to declare one and it is gonna use Controller#not_found instead
|
45
|
+
# But if it is declared, keep in mind it's a catch-all so make it deal with args
|
46
|
+
@articles = Post.all
|
47
|
+
erb :index
|
48
|
+
end
|
49
|
+
|
50
|
+
def post(id=nil)
|
51
|
+
@post = Post[id]
|
52
|
+
if @post.nil?
|
53
|
+
not_found
|
54
|
+
else
|
55
|
+
erb :post
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def say(listener='me', *words)
|
60
|
+
"Hey #{listener} I don't need ERB to tell you that #{words.join(' ')}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def not_found(*args)
|
64
|
+
# This one is defined by Golem but here we decided to override it
|
65
|
+
# Like :index this method receives the arguments in order to make something with it
|
66
|
+
Email.alert('Too many people are looking for porn here') if args.includes?("porn")
|
67
|
+
super(args)
|
68
|
+
end
|
69
|
+
|
70
|
+
after do
|
71
|
+
Spy.analyse.send_info_to([:government, :facebook, :google, :james_bond])
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
Hopefully no headache.
|
77
|
+
|
78
|
+
WHAT GOLEM DOES NOT
|
79
|
+
===================
|
80
|
+
|
81
|
+
- Support templates other than ERB (I plan to use Tilt more cleverly though in order to achieve that without selling my soul)
|
82
|
+
- Session/Cookies administration (Like for many things, use a middleware instead ex: Rack::Session::Cookies)
|
83
|
+
- Prepare the coffee (Emacs does but Ed is the standard text editor)
|
84
|
+
- So many things, why bother...
|
data/lib/rack/golem.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Rack::Golem
|
2
|
+
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
extend ClassMethods
|
6
|
+
include InstanceMethods
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
attr_reader :before_block, :after_block
|
12
|
+
def before(&block); @before_block = block; end
|
13
|
+
def after(&block); @after_block = block; end
|
14
|
+
def dispatcher(&block); @dispatcher_block = block; end
|
15
|
+
def dispatcher_block
|
16
|
+
@dispatcher_block || proc{
|
17
|
+
@path_atoms = @r.path_info.split('/').find_all{|s| s!=''}
|
18
|
+
@action, *@action_arguments = @path_atoms
|
19
|
+
unless public_methods.include?(@action)
|
20
|
+
if public_methods.include?('index')
|
21
|
+
@action, @action_arguments = 'index', @path_atoms
|
22
|
+
else
|
23
|
+
@action, @action_arguments = 'not_found', @path_atoms
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
instance_eval(&self.class.before_block) unless self.class.before_block.nil?
|
28
|
+
|
29
|
+
@res.write(self.__send__(@action,*@action_arguments))
|
30
|
+
|
31
|
+
instance_eval(&self.class.after_block) unless self.class.after_block.nil?
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module InstanceMethods
|
37
|
+
def initialize(app=nil); @app = app; end
|
38
|
+
def call(env); dup.call!(env); end
|
39
|
+
def call!(env)
|
40
|
+
@r = ::Rack::Request.new(env)
|
41
|
+
@res = ::Rack::Response.new
|
42
|
+
instance_eval(&self.class.dispatcher_block)
|
43
|
+
@res.status==404&&!@app.nil? ? @app.call(env) : @res.finish
|
44
|
+
end
|
45
|
+
def not_found(*args)
|
46
|
+
@res.status = 404
|
47
|
+
@res.headers['X-Cascade']='pass'
|
48
|
+
"Not Found: #{@r.path_info}"
|
49
|
+
end
|
50
|
+
def erb(template)
|
51
|
+
@@tilt_cache ||= {}
|
52
|
+
if @@tilt_cache.has_key?(template)
|
53
|
+
template_obj = @@tilt_cache[template]
|
54
|
+
else
|
55
|
+
erb_extention = @r.env['erb.extention'] || ".erb"
|
56
|
+
views_location = @r.env['erb.location'] || ::Dir.pwd+'/views/'
|
57
|
+
views_location << '/' unless views_location[-1]==?/
|
58
|
+
template_obj = Tilt.new("#{views_location}#{template}#{erb_extention}")
|
59
|
+
@@tilt_cache.store(template,template_obj) if ENV['RACK_ENV']=='production'
|
60
|
+
end
|
61
|
+
template_obj.render(self)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/lib/rack_golem.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rack/golem'
|
data/rack-golem.gemspec
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'rack-golem'
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.summary = "A Controller middleware that is euh... basic"
|
6
|
+
s.description = "A Controller middleware that is euh... basic. I would say it is a sort of Ramaze for kids"
|
7
|
+
s.files = `git ls-files`.split("\n").sort
|
8
|
+
s.require_path = './lib'
|
9
|
+
s.author = "Mickael Riga"
|
10
|
+
s.email = "mig@campbellhay.com"
|
11
|
+
s.homepage = "http://www.campbellhay.com"
|
12
|
+
end
|
data/test/spec_golem.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bacon'
|
3
|
+
require 'rack'
|
4
|
+
require 'rack/lobster'
|
5
|
+
require 'fileutils' # fix Rack missing
|
6
|
+
|
7
|
+
Bacon.summary_on_exit
|
8
|
+
|
9
|
+
# Helpers
|
10
|
+
F = ::File
|
11
|
+
D = ::Dir
|
12
|
+
ROOT = F.dirname(__FILE__)+'/..'
|
13
|
+
$:.unshift ROOT+'/lib'
|
14
|
+
require 'rack/golem'
|
15
|
+
|
16
|
+
# =========
|
17
|
+
# = Basic =
|
18
|
+
# =========
|
19
|
+
|
20
|
+
class Basic
|
21
|
+
include Rack::Golem
|
22
|
+
def no_arg; 'nothing'; end
|
23
|
+
def with_args(a,b); '%s+%s' % [a,b]; end
|
24
|
+
def splat_arg(*a); a.join('+'); end
|
25
|
+
private
|
26
|
+
def no_way; 'This is private'; end
|
27
|
+
end
|
28
|
+
BasicR = ::Rack::MockRequest.new(::Rack::Lint.new(Basic.new))
|
29
|
+
BasicLobsterR = ::Rack::MockRequest.new(::Rack::Lint.new(Basic.new(::Rack::Lobster.new)))
|
30
|
+
|
31
|
+
# ==========
|
32
|
+
# = Filter =
|
33
|
+
# ==========
|
34
|
+
|
35
|
+
class Filter
|
36
|
+
include Rack::Golem
|
37
|
+
before{@res.write @action=='not_found' ? @action_arguments.join('+') : 'before+'}
|
38
|
+
after{@res.write '+after'}
|
39
|
+
def wrapped; 'wrapped'; end
|
40
|
+
end
|
41
|
+
FilterR = ::Rack::MockRequest.new(::Rack::Lint.new(Filter.new))
|
42
|
+
|
43
|
+
# ===========
|
44
|
+
# = Indexed =
|
45
|
+
# ===========
|
46
|
+
|
47
|
+
class Indexed
|
48
|
+
include Rack::Golem
|
49
|
+
before{ @res.write("action=#{@action} args=#{@action_arguments.join(',')} ") if @r['switch']=='true' }
|
50
|
+
def index(*a); a.join('+'); end
|
51
|
+
def exist(*a); a.join('+'); end
|
52
|
+
end
|
53
|
+
IndexedR = ::Rack::MockRequest.new(::Rack::Lint.new(Indexed.new))
|
54
|
+
|
55
|
+
# =========
|
56
|
+
# = Specs =
|
57
|
+
# =========
|
58
|
+
|
59
|
+
describe "Golem" do
|
60
|
+
it "Should dispatch on a method with no arguments" do
|
61
|
+
BasicR.get('/no_arg').body.should=='nothing'
|
62
|
+
end
|
63
|
+
it "Should dispatch on a method with arguments" do
|
64
|
+
BasicR.get('/with_args/a/b').body.should=='a+b'
|
65
|
+
end
|
66
|
+
it "Should dispatch on a method with splat argument" do
|
67
|
+
BasicR.get('/splat_arg/a/b/c/d').body.should=='a+b+c+d'
|
68
|
+
end
|
69
|
+
it "Should not dispatch if the method is private or does not exist" do
|
70
|
+
r = BasicR.get('/no_way')
|
71
|
+
r.status.should==404
|
72
|
+
r.body.should=='Not Found: /no_way'
|
73
|
+
r = BasicR.get('/no')
|
74
|
+
r.status.should==404
|
75
|
+
r.body.should=='Not Found: /no'
|
76
|
+
end
|
77
|
+
it "Should follow the rack stack if response is 404 and there are middlewares below" do
|
78
|
+
r = BasicLobsterR.get("/no_way")
|
79
|
+
r.status.should==200
|
80
|
+
end
|
81
|
+
it "Should provide filters" do
|
82
|
+
FilterR.get('/wrapped').body.should=="before+wrapped+after"
|
83
|
+
end
|
84
|
+
it "Should provide arguments in filter when page is not_found" do
|
85
|
+
FilterR.get('/a/b/c/d').body.should=="a+b+c+dNot Found: /a/b/c/d+after"
|
86
|
+
end
|
87
|
+
it "Should send everything to :index if it exists and there is no matching method for first arg" do
|
88
|
+
IndexedR.get('/exist/a/b/c/d').body.should=='a+b+c+d'
|
89
|
+
Indexed.new.public_methods.include?(:index)
|
90
|
+
IndexedR.get('/a/b/c/d').body.should=='a+b+c+d'
|
91
|
+
end
|
92
|
+
it "Should set dispatch-specific variables correctly when defaulting to :index" do
|
93
|
+
IndexedR.get('/a/b/c/d?switch=true').body.should=="action=index args=a,b,c,d a+b+c+d"
|
94
|
+
end
|
95
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-golem
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Mickael Riga
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-09-22 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: A Controller middleware that is euh... basic. I would say it is a sort of Ramaze for kids
|
23
|
+
email: mig@campbellhay.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- README.md
|
32
|
+
- lib/rack/golem.rb
|
33
|
+
- lib/rack_golem.rb
|
34
|
+
- rack-golem.gemspec
|
35
|
+
- test/spec_golem.rb
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://www.campbellhay.com
|
38
|
+
licenses: []
|
39
|
+
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
require_paths:
|
44
|
+
- ./lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
hash: 3
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.4.2
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: A Controller middleware that is euh... basic
|
70
|
+
test_files: []
|
71
|
+
|