manveru-innate 2009.02.21 → 2009.02.25
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +112 -0
- data/MANIFEST +6 -3
- data/Rakefile +2 -5
- data/example/app/retro_games.rb +2 -2
- data/example/app/todo/layout/default.erb +11 -0
- data/example/app/todo/spec/todo.rb +63 -0
- data/example/app/todo/start.rb +51 -0
- data/example/app/todo/view/index.erb +39 -0
- data/example/app/whywiki_erb/layout/wiki.html.erb +1 -1
- data/example/app/whywiki_erb/start.rb +3 -7
- data/example/app/whywiki_erb/view/edit.html.erb +1 -1
- data/example/app/whywiki_erb/view/index.html.erb +6 -4
- data/example/custom_middleware.rb +5 -13
- data/example/hello.rb +1 -2
- data/example/howto_spec.rb +14 -39
- data/example/link.rb +5 -13
- data/example/session.rb +16 -20
- data/innate.gemspec +7 -4
- data/lib/innate/action.rb +8 -7
- data/lib/innate/adapter.rb +1 -1
- data/lib/innate/cache.rb +9 -0
- data/lib/innate/core_compatibility/basic_object.rb +1 -0
- data/lib/innate/helper.rb +5 -5
- data/lib/innate/node.rb +18 -17
- data/lib/innate/options.rb +2 -2
- data/lib/innate/spec.rb +25 -4
- data/lib/innate/state.rb +12 -4
- data/lib/innate/traited.rb +55 -3
- data/lib/innate/version.rb +1 -1
- data/lib/innate/view/erb.rb +1 -1
- data/lib/innate/view/none.rb +2 -2
- data/lib/innate/view.rb +4 -2
- data/lib/innate.rb +137 -104
- data/spec/example/hello.rb +0 -1
- data/spec/example/link.rb +3 -7
- data/spec/example/session.rb +28 -0
- data/spec/innate/helper/redirect.rb +1 -4
- data/spec/innate/node/only_view.html +1 -0
- data/spec/innate/node.rb +12 -0
- metadata +8 -5
- data/example/error_handling.rb +0 -31
- data/example/providing_hash.rb +0 -46
- data/lib/innate/setup.rb +0 -23
data/innate.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "innate"
|
3
|
-
s.version = "2009.02.
|
3
|
+
s.version = "2009.02.25"
|
4
4
|
|
5
5
|
s.summary = "Powerful web-framework wrapper for Rack."
|
6
6
|
s.description = "Simple, straight-forward, base for web-frameworks."
|
@@ -20,17 +20,19 @@ Gem::Specification.new do |s|
|
|
20
20
|
"README.md",
|
21
21
|
"Rakefile",
|
22
22
|
"example/app/retro_games.rb",
|
23
|
+
"example/app/todo/layout/default.erb",
|
24
|
+
"example/app/todo/spec/todo.rb",
|
25
|
+
"example/app/todo/start.rb",
|
26
|
+
"example/app/todo/view/index.erb",
|
23
27
|
"example/app/whywiki_erb/layout/wiki.html.erb",
|
24
28
|
"example/app/whywiki_erb/spec/wiki.rb",
|
25
29
|
"example/app/whywiki_erb/start.rb",
|
26
30
|
"example/app/whywiki_erb/view/edit.html.erb",
|
27
31
|
"example/app/whywiki_erb/view/index.html.erb",
|
28
32
|
"example/custom_middleware.rb",
|
29
|
-
"example/error_handling.rb",
|
30
33
|
"example/hello.rb",
|
31
34
|
"example/howto_spec.rb",
|
32
35
|
"example/link.rb",
|
33
|
-
"example/providing_hash.rb",
|
34
36
|
"example/session.rb",
|
35
37
|
"innate.gemspec",
|
36
38
|
"lib/innate.rb",
|
@@ -67,7 +69,6 @@ Gem::Specification.new do |s|
|
|
67
69
|
"lib/innate/route.rb",
|
68
70
|
"lib/innate/session.rb",
|
69
71
|
"lib/innate/session/flash.rb",
|
70
|
-
"lib/innate/setup.rb",
|
71
72
|
"lib/innate/spec.rb",
|
72
73
|
"lib/innate/state.rb",
|
73
74
|
"lib/innate/state/accessor.rb",
|
@@ -83,6 +84,7 @@ Gem::Specification.new do |s|
|
|
83
84
|
"lib/rack/reloader.rb",
|
84
85
|
"spec/example/hello.rb",
|
85
86
|
"spec/example/link.rb",
|
87
|
+
"spec/example/session.rb",
|
86
88
|
"spec/helper.rb",
|
87
89
|
"spec/innate/action/layout.rb",
|
88
90
|
"spec/innate/action/layout/file_layout.erb",
|
@@ -110,6 +112,7 @@ Gem::Specification.new do |s|
|
|
110
112
|
"spec/innate/node/another_layout/another_layout.erb",
|
111
113
|
"spec/innate/node/bar.html",
|
112
114
|
"spec/innate/node/foo.html.erb",
|
115
|
+
"spec/innate/node/only_view.html",
|
113
116
|
"spec/innate/node/with_layout.erb",
|
114
117
|
"spec/innate/options.rb",
|
115
118
|
"spec/innate/parameter.rb",
|
data/lib/innate/action.rb
CHANGED
@@ -3,12 +3,14 @@ module Innate
|
|
3
3
|
:wish, :options, :variables, :value, :view_value, :name ]
|
4
4
|
|
5
5
|
class Action < Struct.new(*ACTION_MEMBERS)
|
6
|
+
# Holds the default values for merging in {Action::create}
|
6
7
|
DEFAULT = {:options => {}, :variables => {}, :params => []}
|
7
8
|
|
8
9
|
# Create a new Action instance.
|
9
10
|
#
|
10
11
|
# @param [Hash, #to_hash] hash used to seed new Action instance
|
11
12
|
# @return [Action] action with the given defaults from hash
|
13
|
+
# @api stable
|
12
14
|
# @author manveru
|
13
15
|
def self.create(hash = {})
|
14
16
|
new(*DEFAULT.merge(hash.to_hash).values_at(*ACTION_MEMBERS))
|
@@ -21,6 +23,7 @@ module Innate
|
|
21
23
|
#
|
22
24
|
# @return [String] The rendition of all nested calls
|
23
25
|
# @see Action#render Node#action_found
|
26
|
+
# @api stable
|
24
27
|
# @author manveru
|
25
28
|
def call
|
26
29
|
Current.actions << self
|
@@ -31,6 +34,7 @@ module Innate
|
|
31
34
|
|
32
35
|
# @return [Binding] binding of the instance for this Action
|
33
36
|
# @see Node#binding
|
37
|
+
# @api stable
|
34
38
|
# @author manveru
|
35
39
|
def binding
|
36
40
|
instance.binding
|
@@ -43,6 +47,7 @@ module Innate
|
|
43
47
|
# @param [Action #instance] from_action
|
44
48
|
# @return [Action] from_action
|
45
49
|
# @see Action#wrap_in_layout
|
50
|
+
# @api unstable
|
46
51
|
# @author manveru
|
47
52
|
def sync_variables(from_action)
|
48
53
|
instance = from_action.instance
|
@@ -132,12 +137,8 @@ module Innate
|
|
132
137
|
way = File.basename(view).gsub!(/.*?#{wish}\./, '') if view
|
133
138
|
way ||= node.provide[wish] || node.provide['html']
|
134
139
|
|
135
|
-
if way
|
136
|
-
|
137
|
-
View.get(way).render(self, string)
|
138
|
-
else
|
139
|
-
raise("No templating engine was found for %p" % way)
|
140
|
-
end
|
140
|
+
return View.render(way, self, string || view) if way
|
141
|
+
raise("No templating engine was found for %p" % way)
|
141
142
|
end
|
142
143
|
|
143
144
|
def wrap_in_layout
|
@@ -156,7 +157,7 @@ module Innate
|
|
156
157
|
return nil, arg
|
157
158
|
end
|
158
159
|
|
159
|
-
#Try to figure out a sane name for current action.
|
160
|
+
# Try to figure out a sane name for current action.
|
160
161
|
def name
|
161
162
|
File.basename((method || view).to_s).split('.').first
|
162
163
|
end
|
data/lib/innate/adapter.rb
CHANGED
@@ -27,7 +27,7 @@ module Innate
|
|
27
27
|
def start(app, options = Innate.options)
|
28
28
|
adapter_name = options[:adapter].to_s.downcase
|
29
29
|
config = { :Host => options[:host], :Port => options[:port] }
|
30
|
-
Log.debug "
|
30
|
+
Log.debug "Using #{adapter_name}"
|
31
31
|
|
32
32
|
if respond_to?(method = "start_#{adapter_name}")
|
33
33
|
send(method, app, config)
|
data/lib/innate/cache.rb
CHANGED
@@ -79,10 +79,19 @@ module Innate
|
|
79
79
|
)
|
80
80
|
end
|
81
81
|
|
82
|
+
# Add all caches from the options.
|
83
|
+
#
|
84
|
+
# @see Innate::setup_dependencies
|
85
|
+
# @api stable
|
86
|
+
# @return [Array] names of caches initialized
|
87
|
+
# @author manveru
|
82
88
|
def self.setup
|
83
89
|
Innate.options.cache.names.each{|name| add(name) }
|
84
90
|
end
|
85
91
|
|
92
|
+
# Add accessors for cache
|
93
|
+
#
|
94
|
+
# @param [Cache] cache
|
86
95
|
def self.register(cache)
|
87
96
|
key = cache.name
|
88
97
|
source = "def self.%s() @%s; end
|
data/lib/innate/helper.rb
CHANGED
@@ -174,11 +174,11 @@ module Innate
|
|
174
174
|
# Figure out files that might have the helper we ask for and then require
|
175
175
|
# the first we find, if any.
|
176
176
|
def try_require(name)
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
177
|
+
found = Dir[glob(name)].first
|
178
|
+
require(File.expand_path(found))
|
179
|
+
rescue Exception => exception
|
180
|
+
Log.error(exception)
|
181
|
+
raise LoadError, "Helper #{name} not found"
|
182
182
|
end
|
183
183
|
|
184
184
|
# Return a nice list of filenames in correct locations with correct
|
data/lib/innate/node.rb
CHANGED
@@ -28,35 +28,35 @@ module Innate
|
|
28
28
|
# Those methods, and all other methods occurring in the ancestors after
|
29
29
|
# {Innate::Node} will not be considered valid action methods and will be
|
30
30
|
# ignored.
|
31
|
-
# * This also means that
|
31
|
+
# * This also means that method_missing will not see any of the requests
|
32
32
|
# coming in.
|
33
33
|
# * If you want an action to act as a catch-all, use `def index(*args)`.
|
34
34
|
|
35
35
|
module Node
|
36
36
|
include Traited
|
37
37
|
|
38
|
-
|
39
|
-
|
38
|
+
DEFAULT_HELPERS = %w[aspect cgi flash link partial redirect send_file]
|
39
|
+
NODE_LIST = Set.new
|
40
40
|
|
41
41
|
trait(:layout => nil, :alias_view => {}, :provide => {},
|
42
|
-
:method_arities => {}, :wrap => [:aspect_wrap])
|
42
|
+
:method_arities => {}, :wrap => [:aspect_wrap], :provide_set => false)
|
43
43
|
|
44
44
|
# Upon inclusion we make ourselves comfortable.
|
45
|
-
def self.included(
|
46
|
-
|
47
|
-
|
45
|
+
def self.included(into)
|
46
|
+
into.__send__(:include, Helper)
|
47
|
+
into.helper(*DEFAULT_HELPERS)
|
48
48
|
|
49
|
-
|
49
|
+
into.extend(Trinity, self)
|
50
50
|
|
51
|
-
|
51
|
+
NODE_LIST << into
|
52
52
|
|
53
|
-
return if
|
54
|
-
|
55
|
-
|
53
|
+
return if into.ancestral_trait[:provide_set]
|
54
|
+
into.provide(:html => :erb, :yaml => :yaml, :json => :json)
|
55
|
+
into.trait(:provide_set => false)
|
56
56
|
end
|
57
57
|
|
58
58
|
def self.setup
|
59
|
-
|
59
|
+
NODE_LIST.each{|node| Innate.map(node.mapping, node) }
|
60
60
|
Log.debug("Mapped Nodes: %p" % DynaMap::MAP)
|
61
61
|
end
|
62
62
|
|
@@ -64,7 +64,7 @@ module Innate
|
|
64
64
|
def mapping
|
65
65
|
mapped = Innate.to(self)
|
66
66
|
return mapped if mapped
|
67
|
-
return '/' if
|
67
|
+
return '/' if NODE_LIST.size == 1
|
68
68
|
"/" << self.name.gsub(/\B[A-Z][^A-Z]/, '_\&').downcase
|
69
69
|
end
|
70
70
|
|
@@ -131,7 +131,7 @@ module Innate
|
|
131
131
|
|
132
132
|
hash = {}
|
133
133
|
formats.each{|pr, as| hash[pr.to_s] = Array[*as].map{|a| a.to_s } }
|
134
|
-
trait(:provide => hash)
|
134
|
+
trait(:provide => hash, :provide_set => true)
|
135
135
|
|
136
136
|
ancestral_trait[:provide]
|
137
137
|
end
|
@@ -282,6 +282,7 @@ module Innate
|
|
282
282
|
|
283
283
|
next unless view or method
|
284
284
|
next unless method if needs_method
|
285
|
+
next unless method if params.any?
|
285
286
|
|
286
287
|
layout = find_layout(name, wish)
|
287
288
|
params ||= []
|
@@ -548,8 +549,8 @@ module Innate
|
|
548
549
|
# @author manveru
|
549
550
|
def wrap_action_call(action, &block)
|
550
551
|
wrap = ancestral_trait[:wrap]
|
551
|
-
|
552
|
-
|
552
|
+
head, *tail = wrap
|
553
|
+
tail.reverse!
|
553
554
|
combined = tail.inject(block){|s,v| lambda{ __send__(v, action, &s) } }
|
554
555
|
__send__(head, action, &combined)
|
555
556
|
end
|
data/lib/innate/options.rb
CHANGED
@@ -8,7 +8,7 @@ module Innate
|
|
8
8
|
|
9
9
|
# This has to speak for itself.
|
10
10
|
options.dsl do
|
11
|
-
o "IP address or hostname that
|
11
|
+
o "IP address or hostname that we respond to - 0.0.0.0 for all",
|
12
12
|
:host, "0.0.0.0", :short => :H
|
13
13
|
|
14
14
|
o "Port for the server",
|
@@ -35,7 +35,7 @@ module Innate
|
|
35
35
|
o "Indicates which default middleware to use, (:dev|:live)",
|
36
36
|
:mode, :dev
|
37
37
|
|
38
|
-
trigger(:mode){|v| Innate.
|
38
|
+
trigger(:mode){|v| Innate.middleware_recompile(v) }
|
39
39
|
|
40
40
|
sub :log do
|
41
41
|
o "Array of parameters for Logger.new, default to stderr for CGI",
|
data/lib/innate/spec.rb
CHANGED
@@ -8,10 +8,11 @@ require(innate) unless defined?(Innate)
|
|
8
8
|
|
9
9
|
module Innate
|
10
10
|
# minimal middleware, no exception handling
|
11
|
-
middleware(:
|
11
|
+
middleware(:spec){|m| m.innate }
|
12
12
|
|
13
|
-
# skip
|
13
|
+
# skip starting adapter
|
14
14
|
options.started = true
|
15
|
+
options.mode = :spec
|
15
16
|
end
|
16
17
|
|
17
18
|
# Shortcut to use persistent cookies via Innate::Mock::Session
|
@@ -36,7 +37,27 @@ shared :session do
|
|
36
37
|
end
|
37
38
|
|
38
39
|
shared :mock do
|
39
|
-
def get(*args)
|
40
|
-
|
40
|
+
def get(*args) Innate::Mock.get(*args) end
|
41
|
+
def post(*args) Innate::Mock.post(*args) end
|
42
|
+
end
|
43
|
+
|
44
|
+
shared :multipart do
|
45
|
+
def multipart(hash)
|
46
|
+
boundary = 'MuLtIpArT56789'
|
47
|
+
data = []
|
48
|
+
hash.each do |key, value|
|
49
|
+
data << "--#{boundary}"
|
50
|
+
data << %(Content-Disposition: form-data; name="#{key}")
|
51
|
+
data << '' << value
|
52
|
+
end
|
53
|
+
data << "--#{boundary}--"
|
54
|
+
body = data.join("\r\n")
|
55
|
+
|
56
|
+
type = "multipart/form-data; boundary=#{boundary}"
|
57
|
+
length = body.respond_to?(:bytesize) ? body.bytesize : body.size
|
58
|
+
|
59
|
+
{ 'CONTENT_TYPE' => type,
|
60
|
+
'CONTENT_LENGTH' => length.to_s,
|
61
|
+
:input => StringIO.new(body) }
|
41
62
|
end
|
42
63
|
end
|
data/lib/innate/state.rb
CHANGED
@@ -14,9 +14,17 @@ module Innate
|
|
14
14
|
STATE = State::Thread.new
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
module SingletonMethods
|
18
|
+
# Use this method to achieve thread-safety for sensitive operations.
|
19
|
+
#
|
20
|
+
# This should be of most use when manipulating files to prevent other
|
21
|
+
# threads from doing the same, no other code will be scheduled during
|
22
|
+
# execution of this method.
|
23
|
+
#
|
24
|
+
# @param [Proc] block the things you want to execute
|
25
|
+
# @see State::Thread#sync State::Fiber#sync
|
26
|
+
def sync(&block)
|
27
|
+
STATE.sync(&block)
|
28
|
+
end
|
21
29
|
end
|
22
30
|
end
|
data/lib/innate/traited.rb
CHANGED
@@ -1,4 +1,29 @@
|
|
1
1
|
module Innate
|
2
|
+
# Traited helps you doing configuration similar to class variables.
|
3
|
+
#
|
4
|
+
# It's built on a simple Hash, where keys are objects and the values the
|
5
|
+
# configuration.
|
6
|
+
# By using {Traited#ancestral_trait} you will get nicely inherited
|
7
|
+
# configuration, where keys later in the ancestors will take precedence.
|
8
|
+
#
|
9
|
+
# @usage
|
10
|
+
# class Foo
|
11
|
+
# include Innate::Traited
|
12
|
+
# trait :hello => 'Hello'
|
13
|
+
#
|
14
|
+
# def initialize
|
15
|
+
# trait :hello => 'World!'
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def show
|
19
|
+
# [class_trait[:hello], trait[:hello], ancestral_trait[:hello]]
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Foo.trait[:hello] # => "Hello"
|
24
|
+
# foo = Foo.new
|
25
|
+
# foo.trait[:hello] # => "World!"
|
26
|
+
# foo.show # => ["Hello", "World!", "World!"]
|
2
27
|
module Traited
|
3
28
|
TRAITS = {}
|
4
29
|
|
@@ -15,11 +40,38 @@ module Innate
|
|
15
40
|
end
|
16
41
|
end
|
17
42
|
|
43
|
+
# Builds a trait from all the ancestors, closer ancestors overwrite distant
|
44
|
+
# ancestors
|
45
|
+
#
|
46
|
+
# class Foo
|
47
|
+
# include Innate::Traited
|
48
|
+
# trait :one => :eins, :first => :erstes
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# class Bar < Foo
|
52
|
+
# trait :two => :zwei
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# class Foobar < Bar
|
56
|
+
# trait :three => :drei, :first => :overwritten
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# Foobar.ancestral_trait
|
60
|
+
# # => {:three => :drei, :two => :zwei, :one => :eins, :first => :overwritten}
|
18
61
|
def ancestral_trait
|
62
|
+
result = {}
|
63
|
+
|
19
64
|
ancs = respond_to?(:ancestors) ? ancestors : self.class.ancestors
|
20
|
-
ancs.
|
21
|
-
|
22
|
-
|
65
|
+
ancs.reverse_each do |anc|
|
66
|
+
result.update(anc.trait) if anc.respond_to?(:trait)
|
67
|
+
end
|
68
|
+
|
69
|
+
result.merge!(trait)
|
70
|
+
end
|
71
|
+
|
72
|
+
# trait for self.class if we are an instance
|
73
|
+
def class_trait
|
74
|
+
respond_to?(:ancestors) ? trait : self.class.trait
|
23
75
|
end
|
24
76
|
end
|
25
77
|
end
|
data/lib/innate/version.rb
CHANGED
data/lib/innate/view/erb.rb
CHANGED
data/lib/innate/view/none.rb
CHANGED
data/lib/innate/view.rb
CHANGED
@@ -8,8 +8,11 @@ module Innate
|
|
8
8
|
|
9
9
|
module_function
|
10
10
|
|
11
|
-
|
11
|
+
def render(ext, action, string)
|
12
|
+
get(ext).render(action, string)
|
13
|
+
end
|
12
14
|
|
15
|
+
# Try to obtain given engine by its registered name.
|
13
16
|
def get(engine_or_ext)
|
14
17
|
return unless engine_or_ext
|
15
18
|
eoe = Array[*engine_or_ext].first.to_s
|
@@ -27,7 +30,6 @@ module Innate
|
|
27
30
|
# class will cause race conditions and one call may return the wrong class
|
28
31
|
# on the first request (before TEMP is set).
|
29
32
|
# No mutex is used in Fiber environment, see Innate::State and subclasses.
|
30
|
-
|
31
33
|
def obtain(klass)
|
32
34
|
STATE.sync do
|
33
35
|
obj = Object
|