merb 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/README +64 -80
  2. data/Rakefile +25 -12
  3. data/bin/merb +2 -223
  4. data/examples/README_EXAMPLES +10 -0
  5. data/examples/skeleton.tar +0 -0
  6. data/lib/merb.rb +48 -21
  7. data/lib/merb/core_ext.rb +12 -2
  8. data/lib/merb/core_ext/merb_class.rb +21 -21
  9. data/lib/merb/core_ext/merb_kernel.rb +60 -0
  10. data/lib/merb/core_ext/merb_object.rb +14 -0
  11. data/lib/merb/core_ext/merb_string.rb +3 -13
  12. data/lib/merb/generators/merb_app/merb_app.rb +33 -0
  13. data/lib/merb/merb_constants.rb +7 -0
  14. data/lib/merb/merb_controller.rb +31 -23
  15. data/lib/merb/merb_drb_server.rb +6 -60
  16. data/lib/merb/merb_exceptions.rb +162 -2
  17. data/lib/merb/merb_handler.rb +8 -19
  18. data/lib/merb/merb_mailer.rb +60 -0
  19. data/lib/merb/merb_router.rb +1 -1
  20. data/lib/merb/merb_server.rb +240 -0
  21. data/lib/merb/merb_upload_handler.rb +1 -1
  22. data/lib/merb/merb_view_context.rb +11 -6
  23. data/lib/merb/mixins/basic_authentication_mixin.rb +11 -13
  24. data/lib/merb/mixins/controller_mixin.rb +12 -6
  25. data/lib/merb/mixins/form_control_mixin.rb +94 -0
  26. data/lib/merb/mixins/render_mixin.rb +50 -24
  27. data/lib/merb/mixins/view_context_mixin.rb +122 -0
  28. data/lib/merb/session/merb_ar_session.rb +13 -14
  29. data/lib/merb/session/merb_memory_session.rb +105 -0
  30. metadata +13 -132
  31. data/examples/app_skeleton/Rakefile +0 -82
  32. data/examples/app_skeleton/dist/app/helpers/global_helper.rb +0 -6
  33. data/examples/app_skeleton/dist/conf/merb.yml +0 -11
  34. data/examples/app_skeleton/dist/conf/merb_init.rb +0 -16
  35. data/examples/app_skeleton/dist/conf/mup.conf +0 -5
  36. data/examples/app_skeleton/dist/conf/router.rb +0 -19
  37. data/examples/app_skeleton/scripts/merb_stop +0 -13
  38. data/examples/app_skeleton/scripts/new_migration +0 -21
  39. data/examples/app_skeleton/test/test_helper.rb +0 -1
  40. data/examples/sample_app/Rakefile +0 -82
  41. data/examples/sample_app/dist/app/controllers/files.rb +0 -31
  42. data/examples/sample_app/dist/app/controllers/posts.rb +0 -71
  43. data/examples/sample_app/dist/app/controllers/test.rb +0 -40
  44. data/examples/sample_app/dist/app/helpers/global_helper.rb +0 -7
  45. data/examples/sample_app/dist/app/helpers/posts_helper.rb +0 -4
  46. data/examples/sample_app/dist/app/models/comment.rb +0 -3
  47. data/examples/sample_app/dist/app/models/post.rb +0 -4
  48. data/examples/sample_app/dist/app/views/files/progress.jerb +0 -3
  49. data/examples/sample_app/dist/app/views/files/start.herb +0 -62
  50. data/examples/sample_app/dist/app/views/files/upload.herb +0 -6
  51. data/examples/sample_app/dist/app/views/layout/application.herb +0 -61
  52. data/examples/sample_app/dist/app/views/layout/foo.herb +0 -6
  53. data/examples/sample_app/dist/app/views/posts/_comments.herb +0 -11
  54. data/examples/sample_app/dist/app/views/posts/comment.jerb +0 -1
  55. data/examples/sample_app/dist/app/views/posts/list.herb +0 -5
  56. data/examples/sample_app/dist/app/views/posts/new.herb +0 -37
  57. data/examples/sample_app/dist/app/views/posts/show.herb +0 -37
  58. data/examples/sample_app/dist/app/views/posts/xml_test.xerb +0 -3
  59. data/examples/sample_app/dist/app/views/shared/_test.herb +0 -1
  60. data/examples/sample_app/dist/app/views/test/foo.herb +0 -2
  61. data/examples/sample_app/dist/app/views/test/hello.herb +0 -5
  62. data/examples/sample_app/dist/app/views/test/json.jerb +0 -1
  63. data/examples/sample_app/dist/conf/merb.yml +0 -11
  64. data/examples/sample_app/dist/conf/merb_init.rb +0 -24
  65. data/examples/sample_app/dist/conf/mup.conf +0 -5
  66. data/examples/sample_app/dist/conf/router.rb +0 -19
  67. data/examples/sample_app/dist/public/images/bg.jpg +0 -0
  68. data/examples/sample_app/dist/public/images/book.gif +0 -0
  69. data/examples/sample_app/dist/public/images/booksmall.gif +0 -0
  70. data/examples/sample_app/dist/public/images/greenright.jpg +0 -0
  71. data/examples/sample_app/dist/public/images/louiecon.gif +0 -0
  72. data/examples/sample_app/dist/public/images/menu.gif +0 -0
  73. data/examples/sample_app/dist/public/images/menuleft.gif +0 -0
  74. data/examples/sample_app/dist/public/images/menuright.gif +0 -0
  75. data/examples/sample_app/dist/public/images/mountain.jpg +0 -0
  76. data/examples/sample_app/dist/public/images/n3.jpg +0 -0
  77. data/examples/sample_app/dist/public/images/nautica.jpg +0 -0
  78. data/examples/sample_app/dist/public/javascripts/application.js +0 -0
  79. data/examples/sample_app/dist/public/javascripts/effects.js +0 -975
  80. data/examples/sample_app/dist/public/javascripts/mup.js +0 -113
  81. data/examples/sample_app/dist/public/javascripts/prototype.js +0 -2264
  82. data/examples/sample_app/dist/public/stylesheets/merb.css +0 -277
  83. data/examples/sample_app/dist/public/test.html +0 -5
  84. data/examples/sample_app/dist/schema/migrations/001_add_comments_to_posts.rb +0 -22
  85. data/examples/sample_app/dist/schema/migrations/002_add_sessions_table.rb +0 -14
  86. data/examples/sample_app/dist/schema/schema.rb +0 -28
  87. data/examples/sample_app/foo.txt +0 -0
  88. data/examples/sample_app/log/merb.4000.pid +0 -1
  89. data/examples/sample_app/script/merb_stop +0 -13
  90. data/examples/sample_app/script/new_migration +0 -21
  91. data/examples/sample_app/test/test_helper.rb +0 -1
  92. data/lib/merb/mixins/javascript_mixin.rb +0 -147
  93. data/lib/merb/session/merb_drb_session.rb +0 -65
  94. data/test/test_helper.rb +0 -1
  95. data/test/unit/route_matcher_test.rb +0 -46
@@ -0,0 +1,10 @@
1
+ I have removed the useless example app from here for now.
2
+ PLease see mrblog for a better sample app:
3
+
4
+ svn co http://svn.devjavu.com/merb/mrblog/trunk
5
+
6
+ To generate your own new merb app first install the gem and then:
7
+
8
+ $ merb -g appname
9
+ or
10
+ $ merb --generate-app appname
Binary file
@@ -3,28 +3,55 @@ require 'mongrel'
3
3
  require 'fileutils'
4
4
  require 'erubis'
5
5
  require 'logger'
6
- require 'mime/types'
7
6
 
7
+ begin
8
+ require 'fjson'
9
+ puts "using fjson"
10
+ rescue LoadError
11
+ require 'json'
12
+ end
8
13
 
9
14
  module Merb
10
- VERSION='0.0.8' unless defined?VERSION
15
+ VERSION='0.0.9' unless defined?VERSION
11
16
  class Server
12
- def self.config
13
- @@merb_opts ||= {}
17
+ class << self
18
+ def config
19
+ @@merb_opts ||= {}
20
+ end
21
+ def method_missing(meth, *args, &block)
22
+ if meth.to_s[-1..-1] == '='
23
+ key = meth.to_s[0..-2].to_sym
24
+ config.send("[]=", key, *args)
25
+ elsif args.empty?
26
+ config[meth]
27
+ else
28
+ super
29
+ end
30
+ end
14
31
  end
15
32
  end
16
33
  end
17
34
 
18
- class MerbControllerError < RuntimeError; end
35
+ module Erubis
36
+ class MEruby < Erubis::Eruby
37
+ include PercentLineEnhancer
38
+ include StringBufferEnhancer
39
+ end
40
+ end
41
+
42
+ def __DIR__; File.dirname(__FILE__); end
19
43
 
20
- MERB_FRAMEWORK_ROOT = File.dirname(__FILE__)
44
+ require File.join(__DIR__, 'merb/core_ext')
21
45
 
22
- MERB_ROOT = Merb::Server.config[:merb_root] || Dir.pwd
23
- DIST_ROOT = Merb::Server.config[:dist_root] || Dir.pwd+'/dist'
46
+ MERB_FRAMEWORK_ROOT = __DIR__
24
47
 
25
- MERB_LOGGER = Logger.new("#{MERB_ROOT}/log/merb.#{Merb::Server.config[:port]}.log")
48
+ MERB_ROOT = Merb::Server.merb_root || Dir.pwd
49
+ DIST_ROOT = Merb::Server.dist_root || Dir.pwd+'/dist'
50
+
51
+ logpath = $TESTING ? "/tmp/merb_test.log" : "#{MERB_ROOT}/log/merb.#{Merb::Server.port}.log"
52
+ MERB_LOGGER = Logger.new(logpath)
26
53
  # DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
27
- MERB_LOGGER.level = case (Merb::Server.config[:log_level].downcase rescue '')
54
+ MERB_LOGGER.level = case (Merb::Server.log_level.downcase rescue '')
28
55
  when 'debug'
29
56
  Logger::DEBUG
30
57
  when 'info'
@@ -40,23 +67,23 @@ MERB_LOGGER.level = case (Merb::Server.config[:log_level].downcase rescue '')
40
67
  else
41
68
  Logger::INFO
42
69
  end
70
+
43
71
 
44
- corelib = File.join(File.dirname(__FILE__), 'merb/core_ext')
45
- Dir.entries(corelib).sort.each {|fn| require File.join(corelib, fn) if fn =~ /\.rb$/}
46
- lib = File.join(File.dirname(__FILE__), 'merb')
72
+
73
+ lib = File.join(__DIR__, 'merb')
47
74
  Dir.entries(lib).sort.each {|fn| require File.join(lib, fn) if fn =~ /\.rb$/}
48
75
 
76
+ require File.join(__DIR__, 'merb/vendor/paginator/paginator')
77
+
49
78
  class Merb::Controller
50
- if Merb::Server.config[:session]
51
- require "drb"
52
- DRb.start_service('druby://localhost:0')
53
- Merb.const_set :DRbSession, DRbObject.new(nil, "druby://#{Merb::Server.config[:host]}:#{Merb::Server.config[:session]}")
54
- require "merb/session/merb_drb_session"
79
+ if Merb::Server.memory_session
80
+ require "merb/session/merb_memory_session"
81
+ Merb::MemorySession.setup
55
82
  include ::Merb::SessionMixin
56
- puts "drb session mixed in"
83
+ puts "memory session mixed in"
57
84
  end
58
85
 
59
- if Merb::Server.config[:sql_session]
86
+ if Merb::Server.sql_session
60
87
  puts "ActiveRecord session mixed in"
61
88
  begin
62
89
  require 'action_controller/flash'
@@ -68,7 +95,7 @@ class Merb::Controller
68
95
  include ::Merb::SessionMixin
69
96
  end
70
97
 
71
- if Merb::Server.config[:basic_auth]
98
+ if Merb::Server.basic_auth
72
99
  require "merb/mixins/basic_authentication_mixin"
73
100
  include ::Merb::Authentication
74
101
  puts "Basic Authentication mixed in"
@@ -1,2 +1,12 @@
1
- require File.dirname(__FILE__)+'/core_ext/merb_kernel'
2
- aquire File.dirname(__FILE__)+'/core_ext/*'
1
+ corelib = __DIR__+'/merb/core_ext'
2
+
3
+ %w[ merb_class
4
+ merb_kernel
5
+ merb_object
6
+ merb_enumerable
7
+ merb_module
8
+ merb_string
9
+ merb_hash
10
+ merb_numeric
11
+ merb_symbol
12
+ ].each {|fn| require File.join(corelib, fn)}
@@ -41,11 +41,11 @@ class Class # :nodoc:
41
41
  cattr_writer(*syms)
42
42
  end
43
43
 
44
- def meta_reader(*syms)
44
+ def shared_reader(*syms)
45
45
  syms.each do |sym|
46
46
  class_eval <<-EOS
47
47
  def self.#{sym}
48
- read_meta_attribute(:#{sym})
48
+ read_shared_attribute(:#{sym})
49
49
  end
50
50
 
51
51
  def #{sym}
@@ -55,11 +55,11 @@ class Class # :nodoc:
55
55
  end
56
56
  end
57
57
 
58
- def meta_writer(*syms)
58
+ def shared_writer(*syms)
59
59
  syms.each do |sym|
60
60
  class_eval <<-EOS
61
61
  def self.#{sym}=(obj)
62
- write_meta_attribute(:#{sym}, obj)
62
+ write_shared_attribute(:#{sym}, obj)
63
63
  end
64
64
 
65
65
  def #{sym}=(obj)
@@ -69,38 +69,38 @@ class Class # :nodoc:
69
69
  end
70
70
  end
71
71
 
72
- def meta_accessor(*syms)
73
- meta_reader(*syms)
74
- meta_writer(*syms)
72
+ def shared_accessor(*syms)
73
+ shared_reader(*syms)
74
+ shared_writer(*syms)
75
75
  end
76
76
 
77
- def meta_attributes
78
- @meta_attributes ||= {}
77
+ def shared_attributes
78
+ @shared_attributes ||= {}
79
79
  end
80
80
 
81
- def write_meta_attribute(key, value)
82
- meta_attributes[key] = value
81
+ def write_shared_attribute(key, value)
82
+ shared_attributes[key] = value
83
83
  end
84
84
 
85
- def read_meta_attribute(key)
86
- meta_attributes[key]
85
+ def read_shared_attribute(key)
86
+ shared_attributes[key]
87
87
  end
88
88
 
89
- def reset_meta_attributes
90
- meta_attributes.clear
89
+ def reset_shared_attributes
90
+ shared_attributes.clear
91
91
  end
92
92
 
93
93
  private
94
- def inherited_with_meta_attributes(child)
95
- inherited_without_meta_attributes(child) if respond_to?(:inherited_without_meta_attributes)
94
+ def inherited_with_shared_attributes(child)
95
+ inherited_without_shared_attributes(child) if respond_to?(:inherited_without_shared_attributes)
96
96
 
97
- new_meta_attributes = meta_attributes.inject({}) do |memo, (key, value)|
97
+ new_shared_attributes = shared_attributes.inject({}) do |memo, (key, value)|
98
98
  memo.update(key => (value.dup rescue value))
99
99
  end
100
100
 
101
- child.instance_variable_set('@meta_attributes', new_meta_attributes)
101
+ child.instance_variable_set('@shared_attributes', new_shared_attributes)
102
102
  end
103
103
 
104
- alias inherited_without_meta_attributes inherited
105
- alias inherited inherited_with_meta_attributes
104
+ alias inherited_without_shared_attributes inherited
105
+ alias inherited inherited_with_shared_attributes
106
106
  end
@@ -13,4 +13,64 @@ module Kernel
13
13
  end
14
14
  end
15
15
  end
16
+
17
+ def rescue_require(sym, message = nil)
18
+ require sym
19
+ rescue LoadError, RuntimeError
20
+ puts message if message
21
+ end
22
+
23
+ # Gives you back the file, line and method of the caller number i
24
+ # Example:
25
+ # __caller_info__(1) # -> ['/usr/lib/ruby/1.8/irb/workspace.rb', '52', 'irb_binding']
26
+
27
+ def __caller_info__(i = 1)
28
+ file, line, meth = caller[i].scan(/(.*?):(\d+):in `(.*?)'/).first
29
+ end
30
+
31
+ # Gives you some context around a specific line in a file.
32
+ # the size argument works in both directions + the actual line,
33
+ # size = 2 gives you 5 lines of source, the returned array has the
34
+ # following format.
35
+ # [
36
+ # line = [
37
+ # lineno = Integer,
38
+ # line = String,
39
+ # is_searched_line = (lineno == initial_lineno)
40
+ # ],
41
+ # ...,
42
+ # ...
43
+ # ]
44
+ # Example:
45
+ # __caller_lines__('/usr/lib/ruby/1.8/debug.rb', 122, 2) # ->
46
+ # [
47
+ # [ 120, " def check_suspend", false ],
48
+ # [ 121, " return if Thread.critical", false ],
49
+ # [ 122, " while (Thread.critical = true; @suspend_next)", true ],
50
+ # [ 123, " DEBUGGER__.waiting.push Thread.current", false ],
51
+ # [ 124, " @suspend_next = false", false ]
52
+ # ]
53
+
54
+ def __caller_lines__ file, line, size = 4
55
+ return [['Template Error!', "problem while rendering", false]] if file =~ /\(erubis\)/
56
+ lines = File.readlines(file)
57
+ current = line.to_i - 1
58
+
59
+ first = current - size
60
+ first = first < 0 ? 0 : first
61
+
62
+ last = current + size
63
+ last = last > lines.size ? lines.size : last
64
+
65
+ log = lines[first..last]
66
+
67
+ area = []
68
+
69
+ log.each_with_index do |line, index|
70
+ index = index + first + 1
71
+ area << [index, line.chomp, index == current + 1]
72
+ end
73
+
74
+ area
75
+ end
16
76
  end
@@ -3,4 +3,18 @@ class Object
3
3
  yield(value)
4
4
  value
5
5
  end
6
+
7
+ def __meta() class << self; self end end
8
+ def meta_eval(&blk) __meta.instance_eval( &blk ) end
9
+ def meta_def(name, &blk) meta_eval { define_method name, &blk } end
10
+ def class_def name, &blk
11
+ self.class.class_eval { define_method name, &blk }
12
+ end
13
+ def blank?
14
+ if respond_to? :empty? then empty?
15
+ elsif respond_to? :zero? then zero?
16
+ else !self
17
+ end
18
+ end
19
+
6
20
  end
@@ -4,7 +4,7 @@ class String
4
4
  # :allow_reloading is set to true in the config
5
5
  # file or command line options.
6
6
  def import
7
- if Merb::Server.config[:allow_reloading]
7
+ if Merb::Server.allow_reloading
8
8
  Object.send(:remove_const, self.camel_case.intern) rescue nil
9
9
  load(self.snake_case + '.rb')
10
10
  else
@@ -14,16 +14,12 @@ class String
14
14
 
15
15
  # "FooBar".snake_case #=> "foo_bar"
16
16
  def snake_case
17
- return self unless self =~ %r/[A-Z]/
18
- self.reverse.scan(%r/[A-Z]+|[^A-Z]*[A-Z]+?/).reverse.map{|word| word.reverse.downcase}.join '_'
17
+ gsub(/\B[A-Z]/, '_\&').downcase
19
18
  end
20
19
 
21
20
  # "foo_bar".camel_case #=> "FooBar"
22
21
  def camel_case
23
- return self if self =~ %r/[A-Z]/ and self !~ %r/_/
24
- words = self.strip.split %r/\s*_+\s*/
25
- words.map!{|w| w.downcase.sub(%r/^./){|c| c.upcase}}
26
- words.join
22
+ split('_').map{|e| e.capitalize}.join
27
23
  end
28
24
 
29
25
  # Concatenates a path
@@ -31,10 +27,4 @@ class String
31
27
  File.join(self, o.to_s)
32
28
  end
33
29
 
34
- def to_const
35
- const = const.to_s.dup
36
- base = const.sub!(/^::/, '') ? Object : ( self.kind_of?(Module) ? self : self.class )
37
- const.split(/::/).inject(base){ |mod, name| mod.const_get(name) }
38
- end
39
-
40
30
  end
@@ -0,0 +1,33 @@
1
+ require 'fileutils'
2
+ require 'find'
3
+
4
+ begin
5
+ require 'archive/tar/minitar'
6
+ rescue LoadError
7
+ puts "You must gem install archive-tar-minitar to use the merb app generator"
8
+ exit!
9
+ end
10
+
11
+ module Merb
12
+
13
+ class AppGenerator
14
+ SKELETON = File.expand_path File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'examples/skeleton.tar')
15
+
16
+ def self.run(path)
17
+ @path = path
18
+ @path = File.expand_path(@path)
19
+ if File.exists? @path
20
+ STDERR.puts "ERROR: Path #{@path} already exists! Aborting!"
21
+ exit 1
22
+ end
23
+
24
+ puts "Copying skeleton app to '#@path'"
25
+ # Unpacks 'test.tar' to 'x', creating 'x' if necessary.
26
+ Archive::Tar::Minitar.unpack(SKELETON, @path)
27
+ puts 'Done'
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
@@ -14,5 +14,12 @@ module Merb
14
14
  :disposition => 'attachment'.freeze
15
15
  }.freeze
16
16
 
17
+ SET_COOKIE = " %s=%s; path=/; expires=%s".freeze
18
+ COOKIE_SPLIT = /[;,] */n.freeze
19
+ COOKIE_REGEXP = /\s*(.+)=(.*)\s*/.freeze
20
+ COOKIE_EXPIRED_TIME = Time.at(0).freeze
21
+ HOUR = 60*60
22
+ DAY = HOUR*24
23
+ WEEK = DAY*7
17
24
  end
18
25
  end
@@ -13,8 +13,8 @@ module Merb
13
13
  # puts that into params as well.
14
14
  class Controller
15
15
 
16
- meta_accessor :layout
17
-
16
+ shared_accessor :layout, :session_id_key, :cache_templates
17
+
18
18
  include Merb::ControllerMixin
19
19
  include Merb::RenderMixin
20
20
  include Merb::ResponderMixin
@@ -37,6 +37,7 @@ module Merb
37
37
  cookies = query_parse(env['HTTP_COOKIE'], ';,')
38
38
  querystring = query_parse(env['QUERY_STRING'])
39
39
  self.layout ||= :application
40
+ self.session_id_key ||= :_session_id
40
41
  @in = req
41
42
  if MULTIPART_REGEXP =~ env['CONTENT_TYPE']
42
43
  boundary_regexp = /(?:\r?\n|\A)#{Regexp::quote("--#$1")}(?:--)?\r$/
@@ -66,7 +67,11 @@ module Merb
66
67
  end
67
68
  io_buffer << chunk
68
69
  end
69
- querystring[name]=attrs if name
70
+ if name =~ /(.*)?\[\]/
71
+ (querystring[$1] ||= []) << attrs
72
+ else
73
+ querystring[name]=attrs if name
74
+ end
70
75
  attrs[:tempfile].rewind if attrs.is_a?MerbHash
71
76
  end
72
77
  elsif @method == :post
@@ -80,7 +85,7 @@ module Merb
80
85
  end
81
86
  end
82
87
  @cookies, @params = cookies.dup, querystring.dup.merge(args)
83
- @cookies.merge!(:session_id => @params[:session_id]) if @params.has_key?(:session_id)
88
+ @cookies.merge!(:_session_id => @params[:_session_id]) if @params.has_key?(:_session_id)
84
89
  @method = @params.delete(:_method).downcase.to_sym if @params.has_key?(:_method)
85
90
  @request = Request.new(@env, @method)
86
91
  MERB_LOGGER.info("Params: #{params.inspect}")
@@ -90,19 +95,19 @@ module Merb
90
95
  start = Time.now
91
96
  setup_session if respond_to?:setup_session
92
97
  cought = catch(:halt) { call_filters(before_filters) }
93
- case cought
98
+ @body = case cought
94
99
  when :filter_chain_completed
95
- @body = send(action)
100
+ send(action)
96
101
  when String
97
- @body = cought
102
+ cought
98
103
  when nil
99
- @body = filters_halted
104
+ filters_halted
100
105
  when Symbol
101
- @body = send(cought)
106
+ send(cought)
102
107
  when Proc
103
- @body = cought.call(self)
108
+ cought.call(self)
104
109
  else
105
- raise MerbControllerError, "The before filter chain is broken dude."
110
+ raise MerbControllerError, "The before filter chain is broken dude. wtf?"
106
111
  end
107
112
  call_filters(after_filters)
108
113
  finalize_session if respond_to?:finalize_session
@@ -145,13 +150,13 @@ module Merb
145
150
  @session
146
151
  end
147
152
 
148
- # meta_accessor sets up a class instance variable that can
153
+ # shared_accessor sets up a class instance variable that can
149
154
  # be unique for each class but also inherits the meta attrs
150
155
  # from its superclasses. Since @@class variables are almost
151
156
  # global vars within an inheritance tree, we use
152
157
  # @class_instance_variables instead
153
- meta_accessor :before_filters
154
- meta_accessor :after_filters
158
+ shared_accessor :before_filters
159
+ shared_accessor :after_filters
155
160
 
156
161
  # calls a filter chain according to rules.
157
162
  def call_filters(filter_set)
@@ -229,18 +234,13 @@ module Merb
229
234
  not both at the same time for the same filter."
230
235
  ) if opts.has_key?(:only) && opts.has_key?(:exclude)
231
236
 
232
- if opts[:only] && opts[:only].is_a?(Symbol)
233
- opts[:only] = [opts[:only]]
234
- end
235
- if opts[:exclude] && opts[:exclude].is_a?(Symbol)
236
- opts[:exclude] = [opts[:exclude]]
237
- end
237
+ opts = shuffle_filters!(opts)
238
238
 
239
239
  case filter
240
240
  when Symbol, String, Proc
241
241
  (self.before_filters ||= []) << [filter, opts]
242
242
  else
243
- raise(MerbControllerError,
243
+ raise(ArgumentError,
244
244
  'filters need to be either a Symbol, String or a Proc'
245
245
  )
246
246
  end
@@ -260,17 +260,25 @@ module Merb
260
260
  "You can specify either :only or :exclude but
261
261
  not both at the same time for the same filter."
262
262
  ) if opts.has_key?(:only) && opts.has_key?(:exclude)
263
+
263
264
  raise(ArgumentError,
264
265
  'after filters can only be a Proc object'
265
266
  ) unless Proc === filter
267
+
268
+ opts = shuffle_filters!(opts)
269
+
270
+ (self.after_filters ||= []) << [filter, opts]
271
+ end
272
+
273
+ def self.shuffle_filters!(opts={})
266
274
  if opts[:only] && opts[:only].is_a?(Symbol)
267
275
  opts[:only] = [opts[:only]]
268
276
  end
269
277
  if opts[:exclude] && opts[:exclude].is_a?(Symbol)
270
278
  opts[:exclude] = [opts[:exclude]]
271
279
  end
272
- (self.after_filters ||= []) << [filter, opts]
273
- end
280
+ return opts
281
+ end
274
282
 
275
283
  end
276
284