manveru-innate 2009.02.06
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/CHANGELOG +1409 -0
- data/COPYING +18 -0
- data/MANIFEST +100 -0
- data/README.md +485 -0
- data/Rakefile +139 -0
- data/example/app/retro_games.rb +57 -0
- data/example/app/whywiki_erb/layout/wiki.html.erb +15 -0
- data/example/app/whywiki_erb/spec/wiki.rb +19 -0
- data/example/app/whywiki_erb/start.rb +45 -0
- data/example/app/whywiki_erb/view/edit.html.erb +6 -0
- data/example/app/whywiki_erb/view/index.html.erb +10 -0
- data/example/custom_middleware.rb +43 -0
- data/example/error_handling.rb +31 -0
- data/example/hello.rb +12 -0
- data/example/howto_spec.rb +60 -0
- data/example/link.rb +35 -0
- data/example/providing_hash.rb +46 -0
- data/example/session.rb +42 -0
- data/innate.gemspec +118 -0
- data/lib/innate.rb +191 -0
- data/lib/innate/action.rb +156 -0
- data/lib/innate/adapter.rb +89 -0
- data/lib/innate/cache.rb +117 -0
- data/lib/innate/cache/api.rb +106 -0
- data/lib/innate/cache/drb.rb +58 -0
- data/lib/innate/cache/file_based.rb +39 -0
- data/lib/innate/cache/marshal.rb +17 -0
- data/lib/innate/cache/memory.rb +22 -0
- data/lib/innate/cache/yaml.rb +17 -0
- data/lib/innate/core_compatibility/basic_object.rb +9 -0
- data/lib/innate/core_compatibility/string.rb +3 -0
- data/lib/innate/current.rb +37 -0
- data/lib/innate/dynamap.rb +81 -0
- data/lib/innate/helper.rb +195 -0
- data/lib/innate/helper/aspect.rb +62 -0
- data/lib/innate/helper/cgi.rb +39 -0
- data/lib/innate/helper/flash.rb +36 -0
- data/lib/innate/helper/link.rb +55 -0
- data/lib/innate/helper/partial.rb +90 -0
- data/lib/innate/helper/redirect.rb +85 -0
- data/lib/innate/helper/send_file.rb +18 -0
- data/lib/innate/log.rb +23 -0
- data/lib/innate/log/color_formatter.rb +43 -0
- data/lib/innate/log/hub.rb +72 -0
- data/lib/innate/mock.rb +49 -0
- data/lib/innate/node.rb +471 -0
- data/lib/innate/options.rb +91 -0
- data/lib/innate/options/dsl.rb +155 -0
- data/lib/innate/request.rb +165 -0
- data/lib/innate/response.rb +18 -0
- data/lib/innate/route.rb +109 -0
- data/lib/innate/session.rb +104 -0
- data/lib/innate/session/flash.rb +94 -0
- data/lib/innate/setup.rb +23 -0
- data/lib/innate/spec.rb +42 -0
- data/lib/innate/state.rb +22 -0
- data/lib/innate/state/accessor.rb +130 -0
- data/lib/innate/state/fiber.rb +68 -0
- data/lib/innate/state/thread.rb +39 -0
- data/lib/innate/traited.rb +20 -0
- data/lib/innate/trinity.rb +22 -0
- data/lib/innate/version.rb +3 -0
- data/lib/innate/view.rb +67 -0
- data/lib/innate/view/erb.rb +17 -0
- data/lib/innate/view/none.rb +9 -0
- data/lib/rack/middleware_compiler.rb +62 -0
- data/lib/rack/reloader.rb +192 -0
- data/spec/example/hello.rb +14 -0
- data/spec/example/link.rb +29 -0
- data/spec/helper.rb +2 -0
- data/spec/innate/cache/common.rb +45 -0
- data/spec/innate/cache/marshal.rb +5 -0
- data/spec/innate/cache/memory.rb +5 -0
- data/spec/innate/cache/yaml.rb +5 -0
- data/spec/innate/dynamap.rb +22 -0
- data/spec/innate/helper.rb +66 -0
- data/spec/innate/helper/aspect.rb +80 -0
- data/spec/innate/helper/cgi.rb +37 -0
- data/spec/innate/helper/flash.rb +148 -0
- data/spec/innate/helper/link.rb +82 -0
- data/spec/innate/helper/partial.rb +66 -0
- data/spec/innate/helper/redirect.rb +148 -0
- data/spec/innate/helper/send_file.rb +21 -0
- data/spec/innate/helper/view/aspect_hello.erb +1 -0
- data/spec/innate/helper/view/locals.erb +1 -0
- data/spec/innate/helper/view/loop.erb +4 -0
- data/spec/innate/helper/view/num.erb +1 -0
- data/spec/innate/helper/view/partial.erb +1 -0
- data/spec/innate/helper/view/recursive.erb +8 -0
- data/spec/innate/mock.rb +84 -0
- data/spec/innate/node.rb +180 -0
- data/spec/innate/node/bar.html +1 -0
- data/spec/innate/node/foo.html.erb +1 -0
- data/spec/innate/node/with_layout.erb +3 -0
- data/spec/innate/options.rb +90 -0
- data/spec/innate/parameter.rb +154 -0
- data/spec/innate/request.rb +73 -0
- data/spec/innate/route.rb +129 -0
- data/spec/innate/session.rb +59 -0
- data/spec/innate/traited.rb +55 -0
- metadata +160 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
module Innate
|
2
|
+
module Helper
|
3
|
+
# Simple access to session.flash.
|
4
|
+
#
|
5
|
+
# Flash is a mechanism using sessions to provide a rotating holder of
|
6
|
+
# key/value pairs.
|
7
|
+
#
|
8
|
+
# Every request that is made will rotate one step, dropping contents stored
|
9
|
+
# two requests ago.
|
10
|
+
#
|
11
|
+
# The purpose of this class is to provide an easy way of setting/retrieving
|
12
|
+
# from the current flash.
|
13
|
+
#
|
14
|
+
# Flash is a way to keep a temporary pairs of keys and values for the duration
|
15
|
+
# of two requests, the current and following.
|
16
|
+
#
|
17
|
+
# Very vague Example:
|
18
|
+
#
|
19
|
+
# On the first request, for example on registering:
|
20
|
+
#
|
21
|
+
# flash[:error] = "You should reconsider your username, it's taken already"
|
22
|
+
# redirect R(self, :register)
|
23
|
+
#
|
24
|
+
# This is the request from the redirect:
|
25
|
+
#
|
26
|
+
# do_stuff if flash[:error]
|
27
|
+
#
|
28
|
+
# On the request after this, flash[:error] is gone.
|
29
|
+
module Flash
|
30
|
+
# Just for convenience
|
31
|
+
def flash
|
32
|
+
session.flash
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Innate
|
2
|
+
module Helper
|
3
|
+
module Link
|
4
|
+
def self.included(into)
|
5
|
+
into.extend(self)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Provide the path to given Node and actions.
|
9
|
+
# Escapes GET parameters.
|
10
|
+
#
|
11
|
+
# Usage, mapping is Pages => '/', Users => '/users':
|
12
|
+
#
|
13
|
+
# Pages.r # => URI('/')
|
14
|
+
# Pages.r(:foo) # => URI('/foo')
|
15
|
+
# Pages.r(:foo, :bar) # => URI('/foo/bar')
|
16
|
+
# Pages.r(:foo, :a => :b) # => URI('/foo?a=b')
|
17
|
+
# Pages.r(:foo, :bar, :a => :b) # => URI('/foo/bar?a=b')
|
18
|
+
#
|
19
|
+
# Users.r # => URI('/users/')
|
20
|
+
# Users.r(:foo) # => URI('/users/foo')
|
21
|
+
# Users.r(:foo, :bar) # => URI('/users/foo/bar')
|
22
|
+
# Users.r(:foo, :a => :b) # => URI('/users/foo?a=b')
|
23
|
+
# Users.r(:foo, :bar, :a => :b) # => URI('/users/foo/bar?a=b')
|
24
|
+
def route(name = '/', *args)
|
25
|
+
hash = {}
|
26
|
+
hashes, names = args.partition{|arg| arg.respond_to?(:merge!) }
|
27
|
+
hashes.each{|to_merge| hash.merge!(to_merge) }
|
28
|
+
|
29
|
+
location = Innate.to(self) || Innate.to(self.class)
|
30
|
+
front = Array[location, name, *names].join('/').squeeze('/')
|
31
|
+
|
32
|
+
if hash.empty?
|
33
|
+
URI(front)
|
34
|
+
else
|
35
|
+
escape = Rack::Utils.method(:escape)
|
36
|
+
query = hash.map{|key, value| "#{escape[key]}=#{escape[value]}" }.join(';')
|
37
|
+
URI("#{front}?#{query}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
alias r route
|
41
|
+
|
42
|
+
# Usage, given Wiki is mapped to `/wiki`:
|
43
|
+
# Wiki.a(:home) # => '<a href="/wiki/home">home</a>'
|
44
|
+
# Wiki.a('home', :home) # => '<a href="/wiki/home">home</a>'
|
45
|
+
# Wiki.a('home', :/) # => '<a href="/wiki/">home</a>'
|
46
|
+
# Wiki.a('foo', :/, :foo => :bar) # => '<a href="/wiki/?foo=bar">foo</a>'
|
47
|
+
def anchor(text, *args)
|
48
|
+
href = args.empty? ? r(text) : r(*args)
|
49
|
+
text = Rack::Utils.escape_html(text)
|
50
|
+
%(<a href="#{href}">#{text}</a>)
|
51
|
+
end
|
52
|
+
alias a anchor
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
|
2
|
+
# All files in this distribution are subject to the terms of the Ruby license.
|
3
|
+
|
4
|
+
module Innate
|
5
|
+
module Helper
|
6
|
+
|
7
|
+
# = Helper::Partial
|
8
|
+
#
|
9
|
+
# === Example Usage
|
10
|
+
#
|
11
|
+
# class MyController
|
12
|
+
# def index
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# def list
|
16
|
+
# plain = request['plain']
|
17
|
+
# "Hello World from List! Plain List == #{plain}"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# <html>
|
23
|
+
# <head><title>Partial Render Index</title></head>
|
24
|
+
# <body>
|
25
|
+
# #{render_partial(Rs(:list), 'plain' => true)}
|
26
|
+
# </body>
|
27
|
+
# </html>
|
28
|
+
module Partial
|
29
|
+
module_function
|
30
|
+
|
31
|
+
# Renders a url 'inline'.
|
32
|
+
#
|
33
|
+
# +url+ normal URL, like you'd use for redirecting.
|
34
|
+
# +options+ optional, will be used as request parameters.
|
35
|
+
#
|
36
|
+
# Issues a mock request to the given +url+ with +options+ turned into
|
37
|
+
# query arguments.
|
38
|
+
def render_partial(url, options = {})
|
39
|
+
uri = URI(url)
|
40
|
+
query = options # Innate::Current.request.params.merge(options)
|
41
|
+
uri.query = Rack::Utils.build_query(query)
|
42
|
+
|
43
|
+
body = nil
|
44
|
+
|
45
|
+
Innate::Mock.session do |session|
|
46
|
+
cookie = Innate::Current.session.cookie
|
47
|
+
session.cookie = cookie
|
48
|
+
body = session.get(uri.to_s, options).body
|
49
|
+
end
|
50
|
+
|
51
|
+
body
|
52
|
+
end
|
53
|
+
|
54
|
+
# Render the template file in view_root of the
|
55
|
+
# current controller.
|
56
|
+
#
|
57
|
+
# TODO:
|
58
|
+
# * the local variable hack isn't working because innate allocates a new
|
59
|
+
# binding
|
60
|
+
# For now one can simply use instance variables, which I prefer anyway.
|
61
|
+
# * Doesn't work for absolute paths, but there are no specs for that yet.
|
62
|
+
def render_template(path, variables = {})
|
63
|
+
path = path.to_s
|
64
|
+
|
65
|
+
ext = File.extname(path)
|
66
|
+
basename = File.basename(path, ext)
|
67
|
+
ext = ext[1..-1]
|
68
|
+
|
69
|
+
action = Innate::Current.action.dup
|
70
|
+
action.view = action.node.find_view(basename, ext)
|
71
|
+
action.method = action.node.find_method(basename, action.params)
|
72
|
+
action.sync_variables(action)
|
73
|
+
action.variables.merge!(variables)
|
74
|
+
|
75
|
+
=begin
|
76
|
+
variables.each do |key, value|
|
77
|
+
value = "ObjectSpace._id2ref(#{value.object_id})"
|
78
|
+
eval "#{key} = #{value}", action.binding
|
79
|
+
end
|
80
|
+
=end
|
81
|
+
|
82
|
+
action.call
|
83
|
+
end
|
84
|
+
|
85
|
+
def render_action(method, *params)
|
86
|
+
render_partial(r(method), *params)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Innate
|
2
|
+
module Helper
|
3
|
+
module Redirect
|
4
|
+
def respond(body, status = 200, header = {})
|
5
|
+
response.write body
|
6
|
+
response.status = status
|
7
|
+
header['Content-Type'] ||= 'text/html'
|
8
|
+
header.each{|k,v| response[k] = v }
|
9
|
+
|
10
|
+
throw(:respond, response)
|
11
|
+
end
|
12
|
+
|
13
|
+
def respond!(body, status = 200, header = {})
|
14
|
+
header['Content-Type'] ||= 'text/html'
|
15
|
+
throw(:respond, Response.new(body, status, header))
|
16
|
+
end
|
17
|
+
|
18
|
+
# +target+ should be anything responding to #to_s.
|
19
|
+
# To check or modify the URI the redirect will go to you may pass a
|
20
|
+
# block, the result value of the block is ignored:
|
21
|
+
#
|
22
|
+
# redirect("/"){|uri| uri.scheme = 'http' }
|
23
|
+
# redirect("/"){|uri| uri.host = 'secure.com' if uri.scheme =~ /s/ }
|
24
|
+
#
|
25
|
+
# +options+ may contain:
|
26
|
+
#
|
27
|
+
# :scheme => "http" | "https" | "ftp" | ...
|
28
|
+
# :host => "localhost" | "foo.com" | "123.123.123.123" | ...
|
29
|
+
# :port => 7000 | "80" | 80 | ...
|
30
|
+
#
|
31
|
+
# :status => 302 | 300 | 303 | ...
|
32
|
+
# :body => "This is a redirect, hold on while we teleport" | ...
|
33
|
+
#
|
34
|
+
# :raw! => true | false | nil | ...
|
35
|
+
#
|
36
|
+
# Note that all options are optional and you may just pass a +target+.
|
37
|
+
|
38
|
+
def redirect(target, options = {})
|
39
|
+
target = target.to_s
|
40
|
+
|
41
|
+
case target
|
42
|
+
when /^http/, /^\//
|
43
|
+
uri = URI(target)
|
44
|
+
else
|
45
|
+
uri = URI("/#{target}")
|
46
|
+
end
|
47
|
+
|
48
|
+
uri.scheme ||= options[:scheme] || request.scheme
|
49
|
+
uri.host ||= options[:host] || request.host
|
50
|
+
uri.port ||= options[:port] || request.port
|
51
|
+
|
52
|
+
uri = URI(uri.to_s)
|
53
|
+
|
54
|
+
yield(uri) if block_given?
|
55
|
+
|
56
|
+
raw_redirect(uri, options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def raw_redirect(target, options = {}, &block)
|
60
|
+
header = {'Location' => target.to_s}
|
61
|
+
status = options[:status] || 302
|
62
|
+
body = options[:body] || redirect_body(target)
|
63
|
+
|
64
|
+
Log.debug "Redirect to: #{target}"
|
65
|
+
throw(:redirect, Response.new(body, status, header, &block))
|
66
|
+
end
|
67
|
+
|
68
|
+
def redirect_body(target)
|
69
|
+
"You are being redirected, please follow this link to: " +
|
70
|
+
"<a href='#{target}'>#{h target}</a>!"
|
71
|
+
end
|
72
|
+
|
73
|
+
def redirect_referrer(fallback = '/')
|
74
|
+
if referer = request.referer and url = request.url
|
75
|
+
referer_uri, request_uri = URI(referer), URI(url)
|
76
|
+
|
77
|
+
redirect(referer) unless referer_uri == request_uri
|
78
|
+
end
|
79
|
+
|
80
|
+
redirect(fallback)
|
81
|
+
end
|
82
|
+
alias redirect_referer redirect_referrer
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Innate
|
2
|
+
module Helper
|
3
|
+
module SendFile
|
4
|
+
# Not optimally performing but convenient way to send files by their
|
5
|
+
# filename.
|
6
|
+
def send_file(filename, content_type = nil)
|
7
|
+
content_type ||= Rack::Mime.mime_type(::File.extname(filename))
|
8
|
+
|
9
|
+
response.body = ::File.readlines(filename, 'rb')
|
10
|
+
response['Content-Length'] = ::File.size(filename).to_s
|
11
|
+
response['Content-Type'] = content_type
|
12
|
+
response.status = 200
|
13
|
+
|
14
|
+
throw(:respond, response)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/innate/log.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'innate/log/hub'
|
2
|
+
require 'innate/log/color_formatter'
|
3
|
+
|
4
|
+
module Innate
|
5
|
+
logdev, *params = options.log.params
|
6
|
+
color = options.log.color
|
7
|
+
color = Logger::ColorFormatter.color?(logdev) if color.nil?
|
8
|
+
|
9
|
+
logger = Logger.new(logdev, *params)
|
10
|
+
|
11
|
+
if color
|
12
|
+
begin
|
13
|
+
require 'win32console' if RUBY_PLATFORM =~ /win32/i
|
14
|
+
|
15
|
+
logger.formatter = Logger::ColorFormatter.new
|
16
|
+
|
17
|
+
rescue LoadError
|
18
|
+
logger.debug "For colors on windows, please `gem install win32console`"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Log = LogHub.new(logger)
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Logger
|
2
|
+
# Extended Formatter that supports ANSI colors.
|
3
|
+
class ColorFormatter < Formatter
|
4
|
+
LEVEL_COLOR = {
|
5
|
+
'DEBUG' => :blue,
|
6
|
+
'INFO' => :white,
|
7
|
+
'WARN' => :yellow,
|
8
|
+
'ERROR' => :red,
|
9
|
+
'FATAL' => :red,
|
10
|
+
'UNKNOWN' => :green,
|
11
|
+
}
|
12
|
+
|
13
|
+
COLOR_CODE = {
|
14
|
+
:reset => 0, :bold => 1, :dark => 2, :underline => 4, :blink => 5,
|
15
|
+
:negative => 7, :black => 30, :red => 31, :green => 32, :yellow => 33,
|
16
|
+
:blue => 34, :magenta => 35, :cyan => 36, :white => 37,
|
17
|
+
}
|
18
|
+
|
19
|
+
FORMAT_TIME = "%Y-%m-%d %H:%M:%S"
|
20
|
+
FORMAT_LINE = "%s [%s $%d] %5s | %s: %s\n"
|
21
|
+
|
22
|
+
def call(severity, time, program, message)
|
23
|
+
hint = severity[0,1]
|
24
|
+
time = format_time(time)
|
25
|
+
pid = $$
|
26
|
+
string = colorize(msg2str(message), severity)
|
27
|
+
|
28
|
+
FORMAT_LINE % [hint, time, pid, severity, program, string]
|
29
|
+
end
|
30
|
+
|
31
|
+
def format_time(time)
|
32
|
+
time.strftime(FORMAT_TIME)
|
33
|
+
end
|
34
|
+
|
35
|
+
def colorize(string, severity)
|
36
|
+
"\e[#{COLOR_CODE[LEVEL_COLOR[severity]]}m#{string}\e[0m"
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.color?(logdev)
|
40
|
+
logdev.respond_to?(:tty?) and logdev.tty?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Innate
|
2
|
+
# Innate only provides logging via stdlib Logger to avoid bloat and
|
3
|
+
# dependencies, you may specify multiple loggers in the Log instance of LogHub
|
4
|
+
# to accomendate your needs, by default we log to $stderr to be compatible with
|
5
|
+
# CGI.
|
6
|
+
#
|
7
|
+
# Please read the documentation of logger.rb (or even better, its source) to
|
8
|
+
# get a feeling of how to use it correctly within Innate
|
9
|
+
#
|
10
|
+
# A few shortcuts:
|
11
|
+
#
|
12
|
+
# 1. Create logger for stderr/stdout
|
13
|
+
# logger = Logger.new($stdout)
|
14
|
+
# logger = Logger.new($stderr)
|
15
|
+
#
|
16
|
+
# 2. Create logger for a file
|
17
|
+
#
|
18
|
+
# logger = Logger.new('test.log')
|
19
|
+
#
|
20
|
+
# 3. Create logger for file object
|
21
|
+
#
|
22
|
+
# file = File.open('test.log', 'a+')
|
23
|
+
# logger = Logger.new(file)
|
24
|
+
#
|
25
|
+
# 4. Create logger with rotation on specified file size
|
26
|
+
#
|
27
|
+
# # 10 files history, 5 MB each
|
28
|
+
# logger = Logger.new('test.log', 10, (5 << 20))
|
29
|
+
#
|
30
|
+
# # 100 files history, 1 MB each
|
31
|
+
# logger = Logger.new('test.log', 100, (1 << 20))
|
32
|
+
#
|
33
|
+
# 5. Create a logger which ages logfiles daily/weekly/monthly
|
34
|
+
#
|
35
|
+
# logger = Logger.new('test.log', 'daily')
|
36
|
+
# logger = Logger.new('test.log', 'weekly')
|
37
|
+
# logger = Logger.new('test.log', 'monthly')
|
38
|
+
|
39
|
+
class LogHub
|
40
|
+
include Logger::Severity
|
41
|
+
|
42
|
+
attr_accessor :loggers, :program, :active
|
43
|
+
|
44
|
+
# +loggers+ should be a list of Logger instances
|
45
|
+
def initialize(*loggers)
|
46
|
+
@loggers = loggers.flatten
|
47
|
+
@program = nil
|
48
|
+
@active = true
|
49
|
+
self.level = DEBUG
|
50
|
+
end
|
51
|
+
|
52
|
+
# set level for all loggers
|
53
|
+
def level=(lvl)
|
54
|
+
@loggers.each{|l| l.level = lvl }
|
55
|
+
@level = lvl
|
56
|
+
end
|
57
|
+
|
58
|
+
def start; @active = true; end
|
59
|
+
def stop; @active = false; end
|
60
|
+
|
61
|
+
def method_missing(meth, *args, &block)
|
62
|
+
eval %~
|
63
|
+
def #{meth}(*args, &block)
|
64
|
+
return unless @active
|
65
|
+
@loggers.each{|l| l.#{meth}(*args, &block) }
|
66
|
+
end
|
67
|
+
~
|
68
|
+
|
69
|
+
send(meth, *args, &block)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/innate/mock.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Innate
|
2
|
+
module Mock
|
3
|
+
HTTP_METHODS = %w[ CONNECT DELETE GET HEAD OPTIONS POST PUT TRACE ]
|
4
|
+
|
5
|
+
HTTP_METHODS.each do |method|
|
6
|
+
(class << self; self; end).
|
7
|
+
send(:define_method, method.downcase){|*args|
|
8
|
+
mock(method, *args)
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.mock(method, *args)
|
13
|
+
mock_request.request(method, *args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.mock_request
|
17
|
+
Rack::MockRequest.new(Innate)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.session
|
21
|
+
yield Session.new
|
22
|
+
end
|
23
|
+
|
24
|
+
class Session
|
25
|
+
attr_accessor :cookie
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@cookie = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
HTTP_METHODS.each do |method|
|
32
|
+
define_method(method.downcase){|*args|
|
33
|
+
extract_cookie(method, *args)
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def extract_cookie(method, path, hash = {})
|
38
|
+
hash['HTTP_COOKIE'] ||= @cookie if @cookie
|
39
|
+
response = Mock::mock(method, path, hash)
|
40
|
+
|
41
|
+
if cookie = response['Set-Cookie']
|
42
|
+
@cookie = cookie
|
43
|
+
end
|
44
|
+
|
45
|
+
response
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|