manveru-innate 2009.03.24 → 2009.04

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/CHANGELOG +354 -0
  2. data/MANIFEST +34 -22
  3. data/README.md +2 -10
  4. data/Rakefile +30 -247
  5. data/example/app/retro_games.rb +8 -8
  6. data/example/app/todo/layout/{default.erb → default.xhtml} +1 -1
  7. data/example/app/todo/view/{index.erb → index.xhtml} +11 -11
  8. data/example/app/whywiki_erb/start.rb +2 -1
  9. data/example/app/whywiki_erb/view/{edit.html.erb → edit.erb} +0 -0
  10. data/example/app/whywiki_erb/view/{index.html.erb → index.erb} +0 -0
  11. data/example/howto_spec.rb +1 -1
  12. data/example/provides.rb +9 -6
  13. data/example/session.rb +3 -3
  14. data/innate.gemspec +23 -127
  15. data/lib/innate/action.rb +24 -13
  16. data/lib/innate/adapter.rb +5 -27
  17. data/lib/innate/cache/file_based.rb +2 -0
  18. data/lib/innate/cache.rb +1 -1
  19. data/lib/innate/current.rb +5 -5
  20. data/lib/innate/dynamap.rb +5 -0
  21. data/lib/innate/helper/cgi.rb +32 -19
  22. data/lib/innate/helper/link.rb +2 -2
  23. data/lib/innate/helper/redirect.rb +1 -1
  24. data/lib/innate/helper/render.rb +87 -0
  25. data/lib/innate/helper/send_file.rb +9 -1
  26. data/lib/innate/helper.rb +20 -29
  27. data/lib/innate/log/hub.rb +1 -1
  28. data/lib/innate/middleware_compiler.rb +1 -15
  29. data/lib/innate/mock.rb +2 -3
  30. data/lib/innate/node.rb +85 -55
  31. data/lib/innate/options/dsl.rb +1 -1
  32. data/lib/innate/options.rb +1 -1
  33. data/lib/innate/request.rb +3 -76
  34. data/lib/innate/response.rb +1 -8
  35. data/lib/innate/session.rb +2 -3
  36. data/lib/innate/spec.rb +6 -50
  37. data/lib/innate/version.rb +1 -1
  38. data/lib/innate/view/erb.rb +1 -5
  39. data/lib/innate/view/etanni.rb +36 -0
  40. data/lib/innate/view/none.rb +1 -1
  41. data/lib/innate/view.rb +14 -16
  42. data/lib/innate.rb +27 -53
  43. data/spec/example/app/retro_games.rb +30 -0
  44. data/spec/example/provides.rb +16 -0
  45. data/spec/example/session.rb +8 -14
  46. data/spec/innate/action/layout/file_layout.xhtml +1 -0
  47. data/spec/innate/action/layout.rb +1 -1
  48. data/spec/innate/helper/aspect.rb +6 -6
  49. data/spec/innate/helper/flash.rb +28 -47
  50. data/spec/innate/helper/link.rb +8 -0
  51. data/spec/innate/helper/redirect.rb +58 -43
  52. data/spec/innate/helper/render.rb +133 -0
  53. data/spec/innate/helper/view/aspect_hello.xhtml +1 -0
  54. data/spec/innate/helper/view/locals.xhtml +1 -0
  55. data/spec/innate/helper/view/loop.xhtml +4 -0
  56. data/spec/innate/helper/view/num.xhtml +1 -0
  57. data/spec/innate/helper/view/partial.xhtml +1 -0
  58. data/spec/innate/helper/view/recursive.xhtml +7 -0
  59. data/spec/innate/node/node.rb +5 -13
  60. data/spec/innate/node/view/another_layout/{another_layout.erb → another_layout.xhtml} +1 -1
  61. data/spec/innate/node/view/{bar.erb → bar.xhtml} +0 -0
  62. data/spec/innate/node/view/foo.html.xhtml +1 -0
  63. data/spec/innate/node/view/{only_view.erb → only_view.xhtml} +0 -0
  64. data/spec/innate/node/view/with_layout.xhtml +1 -0
  65. data/spec/innate/provides/list.html.xhtml +1 -0
  66. data/spec/innate/provides/list.txt.xhtml +1 -0
  67. data/spec/innate/provides.rb +2 -2
  68. data/spec/innate/request.rb +0 -9
  69. data/spec/innate/session.rb +14 -15
  70. data/spec/innate/state/fiber.rb +8 -7
  71. data/tasks/bacon.rake +66 -0
  72. data/tasks/changelog.rake +18 -0
  73. data/tasks/gem.rake +22 -0
  74. data/tasks/gem_installer.rake +76 -0
  75. data/tasks/grancher.rake +12 -0
  76. data/tasks/install_dependencies.rake +4 -0
  77. data/tasks/manifest.rake +4 -0
  78. data/tasks/rcov.rake +19 -0
  79. data/tasks/release.rake +51 -0
  80. data/tasks/reversion.rake +8 -0
  81. data/tasks/setup.rake +28 -0
  82. metadata +41 -38
  83. data/lib/innate/core_compatibility/basic_object.rb +0 -10
  84. data/lib/innate/core_compatibility/string.rb +0 -3
  85. data/lib/innate/helper/partial.rb +0 -93
  86. data/spec/innate/action/layout/file_layout.erb +0 -1
  87. data/spec/innate/helper/partial.rb +0 -101
  88. data/spec/innate/helper/view/aspect_hello.erb +0 -1
  89. data/spec/innate/helper/view/locals.erb +0 -1
  90. data/spec/innate/helper/view/loop.erb +0 -4
  91. data/spec/innate/helper/view/num.erb +0 -1
  92. data/spec/innate/helper/view/partial.erb +0 -1
  93. data/spec/innate/helper/view/recursive.erb +0 -8
  94. data/spec/innate/node/view/foo.html.erb +0 -1
  95. data/spec/innate/node/view/with_layout.erb +0 -1
  96. data/spec/innate/provides/list.html.erb +0 -1
  97. data/spec/innate/provides/list.txt.erb +0 -1
data/lib/innate/node.rb CHANGED
@@ -28,7 +28,8 @@ module Innate
28
28
  module Node
29
29
  include Traited
30
30
 
31
- DEFAULT_HELPERS = %w[aspect cgi flash link partial redirect send_file]
31
+ attr_reader :method_arities, :layout_templates, :view_templates
32
+
32
33
  NODE_LIST = Set.new
33
34
 
34
35
  # These traits are inherited into ancestors, changing a trait in an
@@ -56,14 +57,12 @@ module Innate
56
57
  # Upon inclusion we make ourselves comfortable.
57
58
  def self.included(into)
58
59
  into.__send__(:include, Helper)
59
- into.helper(*DEFAULT_HELPERS)
60
-
61
60
  into.extend(Trinity, self)
62
61
 
63
62
  NODE_LIST << into
64
63
 
65
64
  return if into.provide_set?
66
- into.provide(:html, :ERB)
65
+ into.provide(:html, :engine => :Etanni)
67
66
  into.trait(:provide_set => false)
68
67
  end
69
68
 
@@ -364,14 +363,16 @@ module Innate
364
363
  # @author manveru
365
364
  def resolve(path)
366
365
  name, wish, engine = find_provide(path)
367
- action = Action.create(:node => self, :wish => wish, :engine => engine)
366
+ node = (respond_to?(:ancestors) && respond_to?(:new)) ? self : self.class
367
+ action = Action.create(:node => node, :wish => wish, :engine => engine, :path => path)
368
368
 
369
- if content_type = ancestral_trait["#{wish}_content_type"]
369
+ if content_type = node.ancestral_trait["#{wish}_content_type"]
370
370
  action.options = {:content_type => content_type}
371
371
  end
372
372
 
373
- update_method_arities
374
- fill_action(action, name)
373
+ node.update_method_arities
374
+ node.update_template_mappings
375
+ node.fill_action(action, name)
375
376
  end
376
377
 
377
378
  # Resolve possible provides for the given +path+ from {provides}.
@@ -422,6 +423,8 @@ module Innate
422
423
  next unless method if params.any?
423
424
  next unless (view = find_view(name, wish)) or method
424
425
 
426
+ params.map!{|param| Rack::Utils.unescape(param) }
427
+
425
428
  action.merge!(:method => method, :view => view, :params => params,
426
429
  :layout => find_layout(name, wish))
427
430
  end
@@ -534,12 +537,10 @@ module Innate
534
537
  @method_arities
535
538
  end
536
539
 
537
- attr_reader :method_arities
538
-
539
540
  # Try to find the best template for the given basename and wish and respect
540
541
  # aliased views.
541
542
  #
542
- # @param [#to_s] file
543
+ # @param [#to_s] action_name
543
544
  # @param [#to_s] wish
544
545
  #
545
546
  # @return [String, nil] depending whether a template could be found
@@ -547,11 +548,11 @@ module Innate
547
548
  # @api external
548
549
  # @see Node#to_template Node#find_aliased_view
549
550
  # @author manveru
550
- def find_view(file, wish)
551
- aliased = find_aliased_view(file, wish)
551
+ def find_view(action_name, wish)
552
+ aliased = find_aliased_view(action_name, wish)
552
553
  return aliased if aliased
553
554
 
554
- to_view(file, wish)
555
+ to_view(action_name, wish)
555
556
  end
556
557
 
557
558
  # Try to find the best template for the given basename and wish.
@@ -559,7 +560,7 @@ module Innate
559
560
  # This method is mostly here for symetry with {to_layout} and to allow you
560
561
  # overriding the template lookup easily.
561
562
  #
562
- # @param [#to_s] file
563
+ # @param [#to_s] action_name
563
564
  # @param [#to_s] wish
564
565
  #
565
566
  # @return [String, nil] depending whether a template could be found
@@ -568,9 +569,9 @@ module Innate
568
569
  # @see {Node#find_view} {Node#to_template} {Node#root_mappings}
569
570
  # {Node#view_mappings} {Node#to_template}
570
571
  # @author manveru
571
- def to_view(file, wish)
572
- path = root_mappings.concat(view_mappings) << file
573
- to_template(path, wish)
572
+ def to_view(action_name, wish)
573
+ return unless files = view_templates[wish.to_s]
574
+ files[action_name.to_s]
574
575
  end
575
576
 
576
577
  # Aliasing one view from another.
@@ -608,9 +609,9 @@ module Innate
608
609
  trait[:alias_view][to.to_s] = node ? [from.to_s, node] : from.to_s
609
610
  end
610
611
 
611
- # Resolve one level of aliasing for the given +file+ and +wish+.
612
+ # Resolve one level of aliasing for the given +action_name+ and +wish+.
612
613
  #
613
- # @param [String] file
614
+ # @param [String] action_name
614
615
  # @param [String] wish
615
616
  #
616
617
  # @return [nil, String] the absolute path to the aliased template or nil
@@ -618,18 +619,21 @@ module Innate
618
619
  # @api internal
619
620
  # @see Node::alias_view Node::find_view
620
621
  # @author manveru
621
- def find_aliased_view(file, wish)
622
- aliased_file, aliased_node = ancestral_trait[:alias_view][file]
622
+ def find_aliased_view(action_name, wish)
623
+ aliased_name, aliased_node = ancestral_trait[:alias_view][action_name]
624
+ return unless aliased_name
625
+
623
626
  aliased_node ||= self
624
- aliased_node.find_view(aliased_file, wish) if aliased_file
627
+ aliased_node.update_view_mappings
628
+ aliased_node.find_view(aliased_name, wish)
625
629
  end
626
630
 
627
- # Find the best matching file for the layout, if any.
631
+ # Find the best matching action_name for the layout, if any.
628
632
  #
629
633
  # This is mostly an abstract method that you might find handy if you want
630
634
  # to do vastly different layout lookup.
631
635
  #
632
- # @param [String] file
636
+ # @param [String] action_name
633
637
  # @param [String] wish
634
638
  #
635
639
  # @return [nil, String] the absolute path to the template or nil
@@ -637,9 +641,9 @@ module Innate
637
641
  # @api external
638
642
  # @see {Node#to_template} {Node#root_mappings} {Node#layout_mappings}
639
643
  # @author manveru
640
- def to_layout(file, wish)
641
- path = root_mappings.concat(layout_mappings) << file
642
- to_template(path, wish)
644
+ def to_layout(action_name, wish)
645
+ return unless files = layout_templates[wish.to_s]
646
+ files[action_name.to_s]
643
647
  end
644
648
 
645
649
  # Define a layout to use on this Node.
@@ -724,11 +728,11 @@ module Innate
724
728
  result = nil
725
729
 
726
730
  atoms.size.downto(0) do |len|
727
- action = atoms[0...len].join('__')
731
+ action_name = atoms[0...len].join('__')
728
732
  params = atoms[len..-1]
729
- action = 'index' if action.empty? and params != ['index']
733
+ action_name = 'index' if action_name.empty? and params != ['index']
730
734
 
731
- return result if result = yield(action, params)
735
+ return result if result = yield(action_name, params)
732
736
  end
733
737
 
734
738
  return nil
@@ -778,31 +782,57 @@ module Innate
778
782
  # Node#path_glob Node#ext_glob
779
783
  # @author manveru
780
784
  def to_template(path, wish)
781
- return unless exts = ext_glob(wish)
782
- glob = "#{path_glob(*path)}.#{exts}"
783
- found = Dir[glob].uniq
785
+ to_view(path, wish) || to_layout(path, wish)
786
+ end
784
787
 
785
- count = found.size
786
- Log.warn("%d views found for %p" % [count, glob]) if count > 1
788
+ def update_template_mappings
789
+ update_view_mappings
790
+ update_layout_mappings
791
+ end
787
792
 
788
- found.first
793
+ def update_view_mappings
794
+ paths = possible_paths_for(view_mappings)
795
+ @view_templates = update_mapping_shared(paths)
789
796
  end
790
797
 
791
- # Produce a glob that can be processed by Dir::[] matching the possible
792
- # paths to the given +elements+.
793
- #
794
- # The +elements+ are an Array that may be nested one level, take care to
795
- # splat if you try to pass an existing Array.
796
- #
797
- # @return [String] glob matching possible paths to the given +elements+
798
- #
799
- # @api internal
800
- # @see Node#to_template
801
- # @author manveru
802
- def path_glob(*elements)
803
- File.join(elements.map{|element|
804
- "{%s}" % [*element].map{|e| e.to_s.gsub('__', '/') }.join(',')
805
- }).gsub(/\/\{\/?\}\//, '/')
798
+ def update_layout_mappings
799
+ paths = possible_paths_for(layout_mappings)
800
+ @layout_templates = update_mapping_shared(paths)
801
+ end
802
+
803
+ def update_mapping_shared(paths)
804
+ mapping = {}
805
+
806
+ provides.each do |wish_key, engine|
807
+ wish = wish_key[/(.*)_handler/, 1]
808
+ ext_glob = ext_glob(wish)
809
+
810
+ paths.reverse_each do |path|
811
+ ::Dir.glob(::File.join(path, "/**/*.#{ext_glob}")) do |file|
812
+ case file.sub(path, '').gsub('/', '__')
813
+ when /^(.*)\.(.*)\.(.*)$/
814
+ action_name, wish_ext, engine_ext = $1, $2, $3
815
+ when /^(.*)\.(.*)$/
816
+ action_name, wish_ext, engine_ext = $1, wish, $2
817
+ end
818
+
819
+ mapping[wish_ext] ||= {}
820
+ mapping[wish_ext][action_name] = file
821
+ end
822
+ end
823
+ end
824
+
825
+ return mapping
826
+ end
827
+
828
+ def possible_paths_for(mappings)
829
+ root_mappings.map{|root_mapping|
830
+ mappings.first.map{|outer_mapping|
831
+ mappings.last.map{|inner_mapping|
832
+ File.join(root_mapping, outer_mapping, inner_mapping, '/')
833
+ }
834
+ }
835
+ }.flatten
806
836
  end
807
837
 
808
838
  # Produce a glob that can be processed by Dir::[] matching the extensions
@@ -839,7 +869,7 @@ module Innate
839
869
  # @api external
840
870
  # @author manveru
841
871
  def root_mappings
842
- [*options.roots].dup
872
+ [*options.roots].flatten
843
873
  end
844
874
 
845
875
  # Set the paths for lookup below the Innate.options.views paths.
@@ -870,7 +900,7 @@ module Innate
870
900
  paths = [*ancestral_trait[:views]]
871
901
  paths = [mapping] if paths.empty?
872
902
 
873
- [*options.views] + paths
903
+ [[*options.views].flatten, [*paths].flatten]
874
904
  end
875
905
 
876
906
  # Set the paths for lookup below the Innate.options.layouts paths.
@@ -901,7 +931,7 @@ module Innate
901
931
  paths = [*ancestral_trait[:layouts]]
902
932
  paths = [mapping] if paths.empty?
903
933
 
904
- [*options.layouts] + paths
934
+ [[*options.layouts].flatten, [*paths].flatten]
905
935
  end
906
936
 
907
937
  def options
@@ -178,7 +178,7 @@ module Innate
178
178
  end
179
179
 
180
180
  # extend your class with this
181
- module Optional
181
+ module Optioned
182
182
  def self.included(into)
183
183
  into.extend(SingletonMethods)
184
184
 
@@ -2,7 +2,7 @@ module Innate
2
2
  # this has to be run after a couple of other files have been required
3
3
 
4
4
  options.dsl do
5
- o "Indicate that calls Innate::start will be ignored",
5
+ o "Innate::start will not start an adapter if true",
6
6
  :started, false
7
7
 
8
8
  o "Will send ::setup to each element during Innate::start",
@@ -71,7 +71,7 @@ module Innate
71
71
  # Both +value+ and the elements of +keys+ will be turned into String by #to_s.
72
72
  def [](value, *keys)
73
73
  return super(value) if keys.empty?
74
- [value, *keys].map{|k| super(k) }
74
+ [value, *keys].map{|key| super(key) }
75
75
  end
76
76
 
77
77
  # the full request URI provided by Rack::Request
@@ -94,8 +94,8 @@ module Innate
94
94
  # # => {'name' => 'jason', 'job' => 'lumberjack'}
95
95
 
96
96
  def subset(*keys)
97
- keys = keys.map{|k| k.to_s }
98
- params.reject{|k,v| not keys.include?(k) }
97
+ keys = keys.map{|key| key.to_s }
98
+ params.reject{|key, value| not keys.include?(key) }
99
99
  end
100
100
 
101
101
  # Try to figure out the domain we are running on, this might work for some
@@ -122,50 +122,6 @@ module Innate
122
122
  uri
123
123
  end
124
124
 
125
- # Try to find out which languages the client would like to have and sort
126
- # them by weight, (most wanted first).
127
- #
128
- # Returns and array of locales from env['HTTP_ACCEPT_LANGUAGE].
129
- # e.g. ["fi", "en", "ja", "fr", "de", "es", "it", "nl", "sv"]
130
- #
131
- # Usage:
132
- #
133
- # request.accept_language
134
- # # => ['en-us', 'en', 'de-at', 'de']
135
- #
136
- # @param [String #to_s] string the value of HTTP_ACCEPT_LANGUAGE
137
- # @return [Array] list of locales
138
- # @see Request#accept_language_with_weight
139
- # @author manveru
140
- def accept_language(string = env['HTTP_ACCEPT_LANGUAGE'])
141
- return [] unless string
142
-
143
- accept_language_with_weight(string).map{|lang, weight| lang }
144
- end
145
- alias locales accept_language
146
-
147
- # Transform the HTTP_ACCEPT_LANGUAGE header into an Array with:
148
- #
149
- # [[lang, weight], [lang, weight], ...]
150
- #
151
- # This algorithm was taken and improved from the locales library.
152
- #
153
- # Usage:
154
- #
155
- # request.accept_language_with_weight
156
- # # => [["en-us", 1.0], ["en", 0.8], ["de-at", 0.5], ["de", 0.3]]
157
- #
158
- # @param [String #to_s] string the value of HTTP_ACCEPT_LANGUAGE
159
- # @return [Array] array of [lang, weight] arrays
160
- # @see Request#accept_language
161
- # @author manveru
162
- def accept_language_with_weight(string = env['HTTP_ACCEPT_LANGUAGE'])
163
- string.to_s.gsub(/\s+/, '').split(',').
164
- map{|chunk| chunk.split(';q=', 2) }.
165
- map{|lang, weight| [lang, weight ? weight.to_f : 1.0] }.
166
- sort_by{|lang, weight| -weight }
167
- end
168
-
169
125
  ipv4 = %w[ 127.0.0.1/32 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 169.254.0.0/16 ]
170
126
  ipv6 = %w[ fc00::/7 fe80::/10 fec0::/10 ::1 ]
171
127
  LOCAL = (ipv4 + ipv6).map{|a| IPAddr.new(a)} unless defined?(LOCAL)
@@ -181,34 +137,5 @@ module Innate
181
137
  rescue ArgumentError => ex
182
138
  raise ArgumentError, ex unless ex.message == 'invalid address'
183
139
  end
184
-
185
- INTERESTING_HTTP_VARIABLES =
186
- (/USER|HOST|REQUEST|REMOTE|FORWARD|REFER|PATH|QUERY|VERSION|KEEP|CACHE/)
187
-
188
- # Interesting HTTP variables from env
189
- def http_variables
190
- env.reject{|key, value| key.to_s !~ INTERESTING_HTTP_VARIABLES }
191
- end
192
- alias http_vars http_variables
193
-
194
- REQUEST_STRING_FORMAT = "#<%s params=%p cookies=%p env=%p>"
195
-
196
- def to_s
197
- REQUEST_STRING_FORMAT % [self.class, params, cookies, http_variables]
198
- end
199
- alias inspect to_s
200
-
201
- # Pretty prints current action with parameters, cookies and enviroment
202
- # variables.
203
- def pretty_print(pp)
204
- pp.object_group(self){
205
- group = { 'params' => params, 'cookies' => cookies, 'env' => http_vars }
206
- group.each do |name, hash|
207
- pp.breakable
208
- pp.text " @#{name}="
209
- pp.nest(name.size + 3){ pp.pp_hash(hash) }
210
- end
211
- }
212
- end
213
140
  end
214
141
  end
@@ -1,19 +1,12 @@
1
1
  module Innate
2
-
3
- # In order to reset the body contents we also need to reset the length set by
4
- # Response#write - until I can submit a patch to Rack and the next release we
5
- # just do this.
6
-
7
2
  class Response < Rack::Response
8
- include Optional
3
+ include Optioned
9
4
 
10
5
  options.dsl do
11
6
  o "Default headers, will not override headers already set",
12
7
  :headers, {'Content-Type' => 'text/html'}
13
8
  end
14
9
 
15
- attr_accessor :length
16
-
17
10
  def reset
18
11
  self.status = 200
19
12
  self.header.delete('Content-Type')
@@ -16,7 +16,7 @@ module Innate
16
16
  # Hopefully we all have 64bit systems by then.
17
17
 
18
18
  class Session
19
- include Optional
19
+ include Optioned
20
20
 
21
21
  options.dsl do
22
22
  o "Key for the session cookie",
@@ -62,8 +62,7 @@ module Innate
62
62
  end
63
63
 
64
64
  def flush(response = @response)
65
- return unless @cache_sid
66
- return if @cache_sid.empty?
65
+ return if !@cache_sid or @cache_sid.empty?
67
66
 
68
67
  flash.rotate!
69
68
  ttl = (Time.at(cookie_value[:expires]) - Time.now).to_i
data/lib/innate/spec.rb CHANGED
@@ -1,10 +1,10 @@
1
+ begin; require 'rubygems'; rescue LoadError; end
2
+
1
3
  require 'bacon'
4
+ require 'rack/test'
5
+ require(File.expand_path("#{__FILE__}/../")) unless defined?(Innate)
2
6
 
3
7
  Bacon.summary_on_exit
4
- # Bacon.extend(Bacon::TestUnitOutput)
5
-
6
- innate = File.expand_path(File.join(File.dirname(__FILE__), '../innate'))
7
- require(innate) unless defined?(Innate)
8
8
 
9
9
  module Innate
10
10
  # minimal middleware, no exception handling
@@ -15,53 +15,9 @@ module Innate
15
15
  options.mode = :spec
16
16
  end
17
17
 
18
- # Shortcut to use persistent cookies via Innate::Mock::Session
19
- #
20
- # Usage:
21
- #
22
- # describe 'something' do
23
- # behaves_like :session
24
- #
25
- # should 'get some stuff' do
26
- # session do |mock|
27
- # mock.get('/')
28
- # end
29
- # end
30
- # end
31
- shared :session do
32
- Innate.setup_dependencies
33
-
34
- def session(&block)
35
- Innate::Mock.session(&block)
36
- end
37
- end
38
-
39
18
  shared :mock do
40
19
  Innate.setup_dependencies
20
+ extend Rack::Test::Methods
41
21
 
42
- def get(*args) Innate::Mock.get(*args) end
43
- def post(*args) Innate::Mock.post(*args) end
44
- def put(*args) Innate::Mock.put(*args) end
45
- def delete(*args) Innate::Mock.delete(*args) end
46
- end
47
-
48
- shared :multipart do
49
- def multipart(hash)
50
- boundary = 'MuLtIpArT56789'
51
- data = []
52
- hash.each do |key, value|
53
- data << "--#{boundary}"
54
- data << %(Content-Disposition: form-data; name="#{key}")
55
- data << '' << value
56
- end
57
- data << "--#{boundary}--"
58
- body = data.join("\r\n")
59
-
60
- type = "multipart/form-data; boundary=#{boundary}"
61
- length = body.respond_to?(:bytesize) ? body.bytesize : body.size
62
-
63
- { 'CONTENT_TYPE' => type,
64
- 'CONTENT_LENGTH' => length.to_s,
65
- :input => StringIO.new(body) }
66
- end
22
+ def app; Innate.middleware; end
67
23
  end
@@ -1,3 +1,3 @@
1
1
  module Innate
2
- VERSION = "2009.03.24"
2
+ VERSION = "2009.04"
3
3
  end
@@ -4,11 +4,7 @@ module Innate
4
4
  module View
5
5
  module ERB
6
6
  def self.call(action, string)
7
- return unless string.respond_to?(:to_str)
8
-
9
- action.copy_variables
10
-
11
- erb = ::ERB.new(string.to_str, nil, '%<>')
7
+ erb = ::ERB.new(string.to_s, nil, '%<>')
12
8
  erb.filename = (action.view || action.method).to_s
13
9
  html = erb.result(action.binding)
14
10
 
@@ -0,0 +1,36 @@
1
+ module Innate
2
+ module View
3
+ module Etanni
4
+ def self.call(action, string)
5
+ template = Innate::Etanni.new(string.to_s)
6
+ html = template.result(action.binding, (action.view || action.method))
7
+ return html, 'text/html'
8
+ end
9
+ end
10
+ end
11
+
12
+ class Etanni
13
+ def initialize(template)
14
+ @template = template
15
+ compile
16
+ end
17
+
18
+ def compile
19
+ temp = @template.dup
20
+ start_heredoc = "T" << Digest::SHA1.hexdigest(temp)
21
+ start_heredoc, end_heredoc = "\n<<#{start_heredoc}.chomp\n", "\n#{start_heredoc}\n"
22
+ bufadd = "_out_ << "
23
+
24
+ temp.gsub!(/<\?r\s+(.*?)\s+\?>/m,
25
+ "#{end_heredoc} \\1; #{bufadd} #{start_heredoc}")
26
+
27
+ @compiled = "_out_ = ''
28
+ #{bufadd} #{start_heredoc} #{temp} #{end_heredoc}
29
+ _out_"
30
+ end
31
+
32
+ def result(binding, filename = '<Etanni>')
33
+ eval(@compiled, binding, filename).to_s.strip
34
+ end
35
+ end
36
+ end
@@ -2,7 +2,7 @@ module Innate
2
2
  module View
3
3
  module None
4
4
  def self.call(action, string)
5
- return string, 'text/html'
5
+ return string.to_s, 'text/html'
6
6
  end
7
7
  end
8
8
  end
data/lib/innate/view.rb CHANGED
@@ -14,16 +14,13 @@ module Innate
14
14
  end
15
15
 
16
16
  # Try to obtain given engine by its registered name.
17
- def get(engine_or_ext)
18
- return unless engine_or_ext
19
- eoe = Array[*engine_or_ext].first.to_s
20
-
21
- if klass = TEMP[eoe]
17
+ def get(engine)
18
+ if klass = TEMP[engine]
22
19
  return klass
23
- elsif klass = ENGINE[eoe]
24
- TEMP[eoe] = obtain(klass)
20
+ elsif klass = ENGINE[engine]
21
+ TEMP[engine] = obtain(klass)
25
22
  else
26
- TEMP[eoe] = obtain(eoe, View)
23
+ TEMP[engine] = obtain(engine, View)
27
24
  end
28
25
  end
29
26
 
@@ -33,7 +30,7 @@ module Innate
33
30
  # No mutex is used in Fiber environment, see Innate::State and subclasses.
34
31
  def obtain(klass, root = Object)
35
32
  STATE.sync do
36
- klass.scan(/\w+/){|part| root = root.const_get(part) }
33
+ klass.to_s.scan(/\w+/){|part| root = root.const_get(part) }
37
34
  root
38
35
  end
39
36
  end
@@ -43,20 +40,21 @@ module Innate
43
40
  # +name+ : the class name of the templating engine wrapper
44
41
  # +exts+ : any number of arguments will be turned into strings via #to_s
45
42
  # that indicate which filename-extensions the templates may have.
46
-
47
43
  def register(klass, *exts)
48
44
  exts.each do |ext|
49
45
  ext = ext.to_s
50
- k = ENGINE[ext]
51
- Log.warn("overwriting %p which is set to %p already" % [ext, k]) if k
46
+ engine = ENGINE[ext]
47
+ Log.warn("overwriting %p, was set to %p" % [ext, engine]) if engine
52
48
  ENGINE[ext] = klass
53
49
  end
54
50
  end
55
51
 
56
- autoload :None, 'innate/view/none'
57
- autoload :ERB, 'innate/view/erb'
52
+ autoload :None, 'innate/view/none'
53
+ autoload :ERB, 'innate/view/erb'
54
+ autoload :Etanni, 'innate/view/etanni'
58
55
 
59
- register 'Innate::View::None', :css, :html, :htm
60
- register 'Innate::View::ERB', :erb
56
+ register 'Innate::View::None', :css, :html, :htm
57
+ register 'Innate::View::ERB', :erb
58
+ register 'Innate::View::Etanni', :xhtml
61
59
  end
62
60
  end