rack-golem 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|