manveru-innate 2009.02.06
Sign up to get free protection for your applications and to get access to all the features.
- 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
|