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.
Files changed (43) hide show
  1. data/CHANGELOG +112 -0
  2. data/MANIFEST +6 -3
  3. data/Rakefile +2 -5
  4. data/example/app/retro_games.rb +2 -2
  5. data/example/app/todo/layout/default.erb +11 -0
  6. data/example/app/todo/spec/todo.rb +63 -0
  7. data/example/app/todo/start.rb +51 -0
  8. data/example/app/todo/view/index.erb +39 -0
  9. data/example/app/whywiki_erb/layout/wiki.html.erb +1 -1
  10. data/example/app/whywiki_erb/start.rb +3 -7
  11. data/example/app/whywiki_erb/view/edit.html.erb +1 -1
  12. data/example/app/whywiki_erb/view/index.html.erb +6 -4
  13. data/example/custom_middleware.rb +5 -13
  14. data/example/hello.rb +1 -2
  15. data/example/howto_spec.rb +14 -39
  16. data/example/link.rb +5 -13
  17. data/example/session.rb +16 -20
  18. data/innate.gemspec +7 -4
  19. data/lib/innate/action.rb +8 -7
  20. data/lib/innate/adapter.rb +1 -1
  21. data/lib/innate/cache.rb +9 -0
  22. data/lib/innate/core_compatibility/basic_object.rb +1 -0
  23. data/lib/innate/helper.rb +5 -5
  24. data/lib/innate/node.rb +18 -17
  25. data/lib/innate/options.rb +2 -2
  26. data/lib/innate/spec.rb +25 -4
  27. data/lib/innate/state.rb +12 -4
  28. data/lib/innate/traited.rb +55 -3
  29. data/lib/innate/version.rb +1 -1
  30. data/lib/innate/view/erb.rb +1 -1
  31. data/lib/innate/view/none.rb +2 -2
  32. data/lib/innate/view.rb +4 -2
  33. data/lib/innate.rb +137 -104
  34. data/spec/example/hello.rb +0 -1
  35. data/spec/example/link.rb +3 -7
  36. data/spec/example/session.rb +28 -0
  37. data/spec/innate/helper/redirect.rb +1 -4
  38. data/spec/innate/node/only_view.html +1 -0
  39. data/spec/innate/node.rb +12 -0
  40. metadata +8 -5
  41. data/example/error_handling.rb +0 -31
  42. data/example/providing_hash.rb +0 -46
  43. 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.21"
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
- # Rack::Mime.mime_type(".#{wish}", 'text/html')
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
@@ -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 "Innate uses #{adapter_name}"
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
@@ -1,3 +1,4 @@
1
+ # We define BasicObject for compatibility with 1.9 if it isn't there yet.
1
2
  class BasicObject
2
3
  # Remove all but these methods
3
4
  # NOTE: __id__ is not there in 1.9, but would give a warning in 1.8
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
- if found = Dir[glob(name)].first
178
- require File.expand_path(found)
179
- else
180
- raise LoadError, "Helper #{name} not found"
181
- end
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 {method_missing} will not see any of the requests
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
- HELPERS = [:aspect, :cgi, :flash, :link, :partial, :redirect, :send_file]
39
- LIST = Set.new
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(obj)
46
- obj.__send__(:include, Helper)
47
- obj.helper(*HELPERS)
45
+ def self.included(into)
46
+ into.__send__(:include, Helper)
47
+ into.helper(*DEFAULT_HELPERS)
48
48
 
49
- obj.extend(Trinity, self)
49
+ into.extend(Trinity, self)
50
50
 
51
- LIST << obj
51
+ NODE_LIST << into
52
52
 
53
- return if obj.provide.any?
54
- # provide .html with no interpolation
55
- obj.provide(:html => :erb, :yaml => :yaml, :json => :json)
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
- LIST.each{|node| Innate.map(node.mapping, node) }
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 Innate::Node::LIST.size == 1
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
- head, tail = wrap[0], wrap[1..-1].reverse
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
@@ -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 Ramaze will respond to - 0.0.0.0 for all",
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.setup_middleware(true) }
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(:innate){|m| m.innate }
11
+ middleware(:spec){|m| m.innate }
12
12
 
13
- # skip merging of options
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
- Innate::Mock.get(*args)
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
- # Log.debug("Innate keeps state with %p" % STATE.class)
18
-
19
- def self.sync(&block)
20
- STATE.sync(&block)
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
@@ -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.reverse.inject({}){|s,v|
21
- v.respond_to?(:trait) ? s.update(v.trait) : s
22
- }.merge(trait)
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
@@ -1,3 +1,3 @@
1
1
  module Innate
2
- VERSION = "2009.02.21"
2
+ VERSION = "2009.02.25"
3
3
  end
@@ -3,7 +3,7 @@ require 'erb'
3
3
  module Innate
4
4
  module View
5
5
  module ERB
6
- def self.render(action, string = action.view)
6
+ def self.render(action, string)
7
7
  return unless string.respond_to?(:to_str)
8
8
 
9
9
  action.copy_variables
@@ -1,8 +1,8 @@
1
1
  module Innate
2
2
  module View
3
3
  module None
4
- def self.render(action, string = nil)
5
- string || action.view
4
+ def self.render(action, string)
5
+ string
6
6
  end
7
7
  end
8
8
  end
data/lib/innate/view.rb CHANGED
@@ -8,8 +8,11 @@ module Innate
8
8
 
9
9
  module_function
10
10
 
11
- # Try to obtain given engine by its registered name.
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