tennpipes-base 3.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.rdoc +294 -0
  4. data/Rakefile +1 -0
  5. data/bin/tennpipes +8 -0
  6. data/lib/tennpipes-base.rb +196 -0
  7. data/lib/tennpipes-base/application.rb +175 -0
  8. data/lib/tennpipes-base/application/application_setup.rb +202 -0
  9. data/lib/tennpipes-base/application/authenticity_token.rb +25 -0
  10. data/lib/tennpipes-base/application/flash.rb +229 -0
  11. data/lib/tennpipes-base/application/params_protection.rb +129 -0
  12. data/lib/tennpipes-base/application/routing.rb +1002 -0
  13. data/lib/tennpipes-base/application/show_exceptions.rb +50 -0
  14. data/lib/tennpipes-base/caller.rb +53 -0
  15. data/lib/tennpipes-base/cli/adapter.rb +33 -0
  16. data/lib/tennpipes-base/cli/base.rb +105 -0
  17. data/lib/tennpipes-base/cli/console.rb +20 -0
  18. data/lib/tennpipes-base/cli/launcher.rb +103 -0
  19. data/lib/tennpipes-base/cli/rake.rb +50 -0
  20. data/lib/tennpipes-base/cli/rake_tasks.rb +72 -0
  21. data/lib/tennpipes-base/command.rb +38 -0
  22. data/lib/tennpipes-base/ext/sinatra.rb +29 -0
  23. data/lib/tennpipes-base/filter.rb +52 -0
  24. data/lib/tennpipes-base/images/404.png +0 -0
  25. data/lib/tennpipes-base/images/500.png +0 -0
  26. data/lib/tennpipes-base/loader.rb +202 -0
  27. data/lib/tennpipes-base/logger.rb +492 -0
  28. data/lib/tennpipes-base/module.rb +58 -0
  29. data/lib/tennpipes-base/mounter.rb +308 -0
  30. data/lib/tennpipes-base/path_router.rb +119 -0
  31. data/lib/tennpipes-base/path_router/compiler.rb +110 -0
  32. data/lib/tennpipes-base/path_router/error_handler.rb +8 -0
  33. data/lib/tennpipes-base/path_router/matcher.rb +123 -0
  34. data/lib/tennpipes-base/path_router/route.rb +169 -0
  35. data/lib/tennpipes-base/reloader.rb +309 -0
  36. data/lib/tennpipes-base/reloader/rack.rb +26 -0
  37. data/lib/tennpipes-base/reloader/storage.rb +55 -0
  38. data/lib/tennpipes-base/router.rb +98 -0
  39. data/lib/tennpipes-base/server.rb +119 -0
  40. data/lib/tennpipes-base/tasks.rb +21 -0
  41. data/lib/tennpipes-base/version.rb +20 -0
  42. data/lib/tennpipes-base/version.rb~ +20 -0
  43. data/test/fixtures/app_gem/Gemfile +4 -0
  44. data/test/fixtures/app_gem/app/app.rb +3 -0
  45. data/test/fixtures/app_gem/app_gem.gemspec +17 -0
  46. data/test/fixtures/app_gem/lib/app_gem.rb +7 -0
  47. data/test/fixtures/app_gem/lib/app_gem/version.rb +3 -0
  48. data/test/fixtures/apps/complex.rb +32 -0
  49. data/test/fixtures/apps/demo_app.rb +7 -0
  50. data/test/fixtures/apps/demo_demo.rb +7 -0
  51. data/test/fixtures/apps/demo_project/api/app.rb +7 -0
  52. data/test/fixtures/apps/demo_project/api/lib/api_lib.rb +3 -0
  53. data/test/fixtures/apps/demo_project/app.rb +7 -0
  54. data/test/fixtures/apps/external_apps/fake_lib.rb +1 -0
  55. data/test/fixtures/apps/external_apps/fake_root.rb +2 -0
  56. data/test/fixtures/apps/helpers/class_methods_helpers.rb +4 -0
  57. data/test/fixtures/apps/helpers/instance_methods_helpers.rb +4 -0
  58. data/test/fixtures/apps/helpers/support.rb +1 -0
  59. data/test/fixtures/apps/helpers/system_helpers.rb +8 -0
  60. data/test/fixtures/apps/kiq.rb +3 -0
  61. data/test/fixtures/apps/lib/myklass.rb +2 -0
  62. data/test/fixtures/apps/lib/myklass/mysubklass.rb +4 -0
  63. data/test/fixtures/apps/models/child.rb +2 -0
  64. data/test/fixtures/apps/models/parent.rb +5 -0
  65. data/test/fixtures/apps/mountable_apps/rack_apps.rb +15 -0
  66. data/test/fixtures/apps/mountable_apps/static.html +1 -0
  67. data/test/fixtures/apps/precompiled_app.rb +19 -0
  68. data/test/fixtures/apps/simple.rb +32 -0
  69. data/test/fixtures/apps/static.rb +10 -0
  70. data/test/fixtures/apps/system.rb +13 -0
  71. data/test/fixtures/apps/system_class_methods_demo.rb +7 -0
  72. data/test/fixtures/apps/system_instance_methods_demo.rb +7 -0
  73. data/test/fixtures/dependencies/a.rb +9 -0
  74. data/test/fixtures/dependencies/b.rb +4 -0
  75. data/test/fixtures/dependencies/c.rb +1 -0
  76. data/test/fixtures/dependencies/circular/e.rb +13 -0
  77. data/test/fixtures/dependencies/circular/f.rb +2 -0
  78. data/test/fixtures/dependencies/circular/g.rb +2 -0
  79. data/test/fixtures/dependencies/d.rb +4 -0
  80. data/test/fixtures/reloadable_apps/external/app/app.rb +6 -0
  81. data/test/fixtures/reloadable_apps/external/app/controllers/base.rb +6 -0
  82. data/test/fixtures/reloadable_apps/main/app.rb +10 -0
  83. data/test/helper.rb +30 -0
  84. data/test/test_application.rb +185 -0
  85. data/test/test_core.rb +93 -0
  86. data/test/test_csrf_protection.rb +208 -0
  87. data/test/test_dependencies.rb +57 -0
  88. data/test/test_filters.rb +389 -0
  89. data/test/test_flash.rb +168 -0
  90. data/test/test_locale.rb +21 -0
  91. data/test/test_logger.rb +295 -0
  92. data/test/test_mounter.rb +302 -0
  93. data/test/test_params_protection.rb +195 -0
  94. data/test/test_reloader_complex.rb +74 -0
  95. data/test/test_reloader_external.rb +21 -0
  96. data/test/test_reloader_simple.rb +101 -0
  97. data/test/test_reloader_system.rb +113 -0
  98. data/test/test_restful_routing.rb +33 -0
  99. data/test/test_router.rb +281 -0
  100. data/test/test_routing.rb +2328 -0
  101. metadata +301 -0
@@ -0,0 +1,175 @@
1
+ require 'tennpipes-base/application/flash'
2
+ require 'tennpipes-base/application/routing'
3
+ require 'tennpipes-base/application/show_exceptions'
4
+ require 'tennpipes-base/application/authenticity_token'
5
+ require 'tennpipes-base/application/application_setup'
6
+ require 'tennpipes-base/application/params_protection'
7
+
8
+ module Tennpipes
9
+ ##
10
+ # Subclasses of this become independent Tennpipes applications
11
+ # (stemming from Sinatra::Application).
12
+ # These subclassed applications can be easily mounted into other
13
+ # Tennpipes applications as well.
14
+ #
15
+ class Application < Sinatra::Base
16
+ register Tennpipes::ApplicationSetup
17
+ register Tennpipes::Routing
18
+ register Tennpipes::ParamsProtection
19
+
20
+ ##
21
+ # Returns the logger for this application.
22
+ #
23
+ # @return [Tennpipes::Logger] Logger associated with this app.
24
+ #
25
+ def logger
26
+ Tennpipes.logger
27
+ end
28
+
29
+ class << self
30
+ def inherited(base)
31
+ begun_at = Time.now
32
+ CALLERS_TO_IGNORE.concat(TENNPIPES_IGNORE_CALLERS)
33
+ super(base)
34
+ base.prerequisites.replace(self.prerequisites.dup)
35
+ base.default_configuration!
36
+ logger.devel :setup, begun_at, base
37
+ end
38
+
39
+ ##
40
+ # Reloads the application files from all defined load paths.
41
+ #
42
+ # This method is used from our Tennpipes Reloader during development mode
43
+ # in order to reload the source files.
44
+ #
45
+ # @return [TrueClass]
46
+ #
47
+ # @example
48
+ # MyApp.reload!
49
+ #
50
+ def reload!
51
+ logger.devel "Reloading application #{settings}"
52
+ reset!
53
+ reset_router!
54
+ Tennpipes.require_dependencies(settings.app_file, :force => true)
55
+ require_dependencies
56
+ default_routes
57
+ default_errors
58
+ I18n.reload! if defined?(I18n)
59
+ true
60
+ end
61
+
62
+ ##
63
+ # Resets application routes to only routes not defined by the user.
64
+ #
65
+ # @return [TrueClass]
66
+ #
67
+ # @example
68
+ # MyApp.reset_routes!
69
+ #
70
+ def reset_routes!
71
+ reset_router!
72
+ default_routes
73
+ true
74
+ end
75
+
76
+ ##
77
+ # Returns the routes of our app.
78
+ #
79
+ # @example
80
+ # MyApp.routes
81
+ #
82
+ def routes
83
+ router.routes
84
+ end
85
+
86
+ ##
87
+ # Returns an absolute path of view in application views folder.
88
+ #
89
+ # @example
90
+ # Admin.view_path 'users/index' #=> "/home/user/test/admin/views/users/index"
91
+ #
92
+ def view_path(view)
93
+ File.expand_path(view, views)
94
+ end
95
+
96
+ ##
97
+ # Returns an absolute path of application layout.
98
+ #
99
+ # @example
100
+ # Admin.layout_path :application #=> "/home/user/test/admin/views/layouts/application"
101
+ #
102
+ def layout_path(layout)
103
+ view_path("layouts/#{layout}")
104
+ end
105
+
106
+ ##
107
+ # Run the Tennpipes app as a self-hosted server using
108
+ # Thin, Mongrel or WEBrick (in that order).
109
+ #
110
+ # @see Tennpipes::Server#start
111
+ #
112
+ def run!(options={})
113
+ return unless Tennpipes.load!
114
+ Tennpipes.mount(settings.to_s).to('/')
115
+ Tennpipes.run!(options)
116
+ end
117
+
118
+ ##
119
+ # Returns default list of path globs to load as dependencies.
120
+ # Appends custom dependency patterns to the be loaded for your Application.
121
+ #
122
+ # @return [Array]
123
+ # list of path globs to load as dependencies
124
+ #
125
+ # @example
126
+ # MyApp.dependencies << "#{Tennpipes.root}/uploaders/**/*.rb"
127
+ # MyApp.dependencies << Tennpipes.root('other_app', 'controllers.rb')
128
+ #
129
+ def dependencies
130
+ [
131
+ 'urls.rb',
132
+ 'config/urls.rb',
133
+ 'mailers/*.rb',
134
+ 'mailers.rb',
135
+ 'controllers/**/*.rb',
136
+ 'controllers.rb',
137
+ 'helpers/**/*.rb',
138
+ 'helpers.rb',
139
+ ].flat_map{ |file| Dir.glob(File.join(settings.root, file)) }
140
+ end
141
+
142
+ ##
143
+ # An array of file to load before your app.rb, basically are files
144
+ # which our app depends on.
145
+ #
146
+ # By default we look for files:
147
+ #
148
+ # # List of default files that we are looking for:
149
+ # yourapp/models.rb
150
+ # yourapp/models/**/*.rb
151
+ # yourapp/lib.rb
152
+ # yourapp/lib/**/*.rb
153
+ #
154
+ # @example Adding a custom prerequisite
155
+ # MyApp.prerequisites << Tennpipes.root('my_app', 'custom_model.rb')
156
+ #
157
+ def prerequisites
158
+ @_prerequisites ||= []
159
+ end
160
+
161
+ def default(option, *args, &block)
162
+ set(option, *args, &block) unless respond_to?(option)
163
+ end
164
+
165
+ protected
166
+
167
+ ##
168
+ # Requires all files within the application load paths.
169
+ #
170
+ def require_dependencies
171
+ Tennpipes.require_dependencies(dependencies, :force => true)
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,202 @@
1
+ module Tennpipes
2
+ ##
3
+ # Holds setup-oriented methods for Tennpipes::Application.
4
+ #
5
+ module ApplicationSetup
6
+ def self.registered(app)
7
+ app.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ ##
12
+ # Defines default settings for Tennpipes application.
13
+ #
14
+ def default_configuration!
15
+ set :app_file, File.expand_path(caller_files.first || $0)
16
+ set :app_name, settings.to_s.underscore.to_sym
17
+
18
+ set :environment, Tennpipes.env
19
+ set :reload, proc { development? }
20
+ set :logging, proc { development? }
21
+
22
+ set :method_override, true
23
+ set :default_builder, 'StandardFormBuilder'
24
+
25
+ default_paths
26
+ default_security
27
+ global_configuration
28
+ setup_prerequisites
29
+ end
30
+
31
+ ##
32
+ # Setup the application by registering initializers, load paths and logger.
33
+ # Invoked automatically when an application is first instantiated.
34
+ #
35
+ # @return [TrueClass]
36
+ #
37
+ def setup_application!
38
+ return if @_configured
39
+ require_dependencies
40
+ default_routes
41
+ default_errors
42
+ setup_locale
43
+ precompile_routes!
44
+ @_configured = true
45
+ end
46
+
47
+ def precompile_routes?
48
+ settings.respond_to?(:precompile_routes) && settings.precompile_routes?
49
+ end
50
+
51
+ def precompile_routes!
52
+ compiled_router.prepare!
53
+ compiled_router.engine.compile!
54
+ end
55
+
56
+ private
57
+
58
+ def default_paths
59
+ set :locale_path, proc { Dir.glob File.join(root, 'locale/**/*.{rb,yml}') }
60
+ set :views, proc { File.join(root, 'views') }
61
+
62
+ set :uri_root, '/'
63
+ set :public_folder, proc { Tennpipes.root('public', uri_root) }
64
+ set :images_path, proc { File.join(public_folder, 'images') }
65
+ end
66
+
67
+ def default_security
68
+ set :protection, :except => :path_traversal
69
+ set :sessions, false
70
+ set :protect_from_csrf, false
71
+ set :report_csrf_failure, false
72
+ set :allow_disabled_csrf, false
73
+ end
74
+
75
+ ##
76
+ # Applies global tennpipes configuration blocks to current application.
77
+ #
78
+ def global_configuration
79
+ Tennpipes.global_configurations.each do |configuration|
80
+ class_eval(&configuration)
81
+ end
82
+ end
83
+
84
+ def setup_prerequisites
85
+ prerequisites.concat(default_prerequisites).uniq!
86
+ Tennpipes.require_dependencies(prerequisites)
87
+ end
88
+
89
+ ##
90
+ # Returns globs of default paths of application prerequisites.
91
+ #
92
+ def default_prerequisites
93
+ [
94
+ '/models.rb',
95
+ '/models/**/*.rb',
96
+ '/lib.rb',
97
+ '/lib/**/*.rb',
98
+ ].map{ |glob| File.join(settings.root, glob) }
99
+ end
100
+
101
+ # Overrides the default middleware for Sinatra based on Tennpipes conventions.
102
+ # Also initializes the application after setting up the middleware.
103
+ def setup_default_middleware(builder)
104
+ setup_sessions builder
105
+ builder.use Sinatra::ExtendedRack if defined?(EventMachine)
106
+ builder.use Tennpipes::ShowExceptions if show_exceptions?
107
+ builder.use Tennpipes::Logger::Rack, uri_root if Tennpipes.logger && logging?
108
+ builder.use Tennpipes::Reloader::Rack if reload?
109
+ builder.use Rack::MethodOverride if method_override?
110
+ builder.use Rack::Head
111
+ register Tennpipes::Flash
112
+ setup_protection builder
113
+ setup_csrf_protection builder
114
+ setup_application!
115
+ end
116
+
117
+ ##
118
+ # We need to add almost __sinatra__ images.
119
+ #
120
+ def default_routes
121
+ configure :development do
122
+ get '*__sinatra__/:image.png' do
123
+ content_type :png
124
+ send_file(File.dirname(__FILE__) + "/../images/#{params[:image]}.png")
125
+ end
126
+ end
127
+ end
128
+
129
+ ##
130
+ # This log errors for production environments.
131
+ #
132
+ def default_errors
133
+ configure :production do
134
+ error ::Exception do
135
+ logger.exception env['sinatra.error']
136
+ halt(500, { 'Content-Type' => 'text/html' }, ['<h1>Internal Server Error</h1>'])
137
+ end unless errors.has_key?(::Exception)
138
+ end
139
+ end
140
+
141
+ def setup_locale
142
+ return unless defined? I18n
143
+ Reloader.special_files += locale_path
144
+ I18n.load_path << locale_path
145
+ I18n.reload!
146
+ end
147
+
148
+ # allow custome session management
149
+ def setup_sessions(builder)
150
+ if sessions.kind_of?(Hash) && sessions[:use]
151
+ builder.use sessions[:use], sessions[:config] || {}
152
+ else
153
+ super
154
+ end
155
+ end
156
+
157
+ # sets up csrf protection for the app
158
+ def setup_csrf_protection(builder)
159
+ check_csrf_protection_dependency
160
+
161
+ if protect_from_csrf?
162
+ options = options_for_csrf_protection_setup
163
+ options.merge!(protect_from_csrf) if protect_from_csrf.kind_of?(Hash)
164
+ builder.use(options[:except] ? Tennpipes::AuthenticityToken : Rack::Protection::AuthenticityToken, options)
165
+ end
166
+ end
167
+
168
+ # returns the options used in the builder for csrf protection setup
169
+ def options_for_csrf_protection_setup
170
+ options = { :logger => logger }
171
+ if report_csrf_failure? || allow_disabled_csrf?
172
+ options.merge!(
173
+ :reaction => :report,
174
+ :report_key => 'protection.csrf.failed'
175
+ )
176
+ end
177
+ options
178
+ end
179
+
180
+ # warn if the protect_from_csrf is active but sessions are not
181
+ def check_csrf_protection_dependency
182
+ if (protect_from_csrf? && !sessions?) && !defined?(Tennpipes::IGNORE_CSRF_SETUP_WARNING)
183
+ warn(<<-ERROR)
184
+ `protect_from_csrf` is activated, but `sessions` seem to be off. To enable csrf
185
+ protection, use:
186
+
187
+ enable :sessions
188
+
189
+ or deactivate protect_from_csrf:
190
+
191
+ disable :protect_from_csrf
192
+
193
+ If you use a different session store, ignore this warning using:
194
+
195
+ # in boot.rb:
196
+ Tennpipes::IGNORE_CSRF_SETUP_WARNING = true
197
+ ERROR
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,25 @@
1
+ module Tennpipes
2
+ class AuthenticityToken < Rack::Protection::AuthenticityToken
3
+ def initialize(app, options = {})
4
+ @app = app
5
+ @except = options[:except]
6
+ @except = Array(@except) unless @except.is_a?(Proc)
7
+ super
8
+ end
9
+
10
+ def call(env)
11
+ if except?(env)
12
+ @app.call(env)
13
+ else
14
+ super
15
+ end
16
+ end
17
+
18
+ def except?(env)
19
+ return false unless @except
20
+ path_info = env['PATH_INFO']
21
+ @except.is_a?(Proc) ? @except.call(env) : @except.any?{|path|
22
+ path.is_a?(Regexp) ? path.match(path_info) : path == path_info }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,229 @@
1
+ module Tennpipes
2
+ module Flash
3
+
4
+ class << self
5
+ def registered(app)
6
+ app.helpers Helpers
7
+ app.after do
8
+ session[:_flash] = @_flash.next if @_flash
9
+ end
10
+ end
11
+ end
12
+
13
+ class Storage
14
+ include Enumerable
15
+
16
+ # @private
17
+ def initialize(session=nil)
18
+ @_now = session || {}
19
+ @_next = {}
20
+ end
21
+
22
+ def now
23
+ @_now
24
+ end
25
+
26
+ def next
27
+ @_next
28
+ end
29
+
30
+ # @since 0.10.8
31
+ # @api public
32
+ def [](type)
33
+ @_now[type]
34
+ end
35
+
36
+ # @since 0.10.8
37
+ # @api public
38
+ def []=(type, message)
39
+ @_next[type] = message
40
+ end
41
+
42
+ # @since 0.10.8
43
+ # @api public
44
+ def delete(type)
45
+ @_now.delete(type)
46
+ self
47
+ end
48
+
49
+ # @since 0.10.8
50
+ # @api public
51
+ def keys
52
+ @_now.keys
53
+ end
54
+
55
+ # @since 0.10.8
56
+ # @api public
57
+ def key?(type)
58
+ @_now.key?(type)
59
+ end
60
+
61
+ # @since 0.10.8
62
+ # @api public
63
+ def each(&block)
64
+ @_now.each(&block)
65
+ end
66
+
67
+ # @since 0.10.8
68
+ # @api public
69
+ def replace(hash)
70
+ @_now.replace(hash)
71
+ self
72
+ end
73
+
74
+ # @since 0.10.8
75
+ # @api public
76
+ def update(hash)
77
+ @_now.update(hash)
78
+ self
79
+ end
80
+ alias_method :merge!, :update
81
+
82
+ # @since 0.10.8
83
+ # @api public
84
+ def sweep
85
+ @_now.replace(@_next)
86
+ @_next = {}
87
+ self
88
+ end
89
+
90
+ # @since 0.10.8
91
+ # @api public
92
+ def keep(key = nil)
93
+ if key
94
+ @_next[key] = @_now[key]
95
+ else
96
+ @_next.merge!(@_now)
97
+ end
98
+ self
99
+ end
100
+
101
+ # @since 0.10.8
102
+ # @api public
103
+ def discard(key = nil)
104
+ if key
105
+ @_next.delete(key)
106
+ else
107
+ @_next = {}
108
+ end
109
+ self
110
+ end
111
+
112
+ # @since 0.10.8
113
+ # @api public
114
+ def clear
115
+ @_now.clear
116
+ end
117
+
118
+ # @since 0.10.8
119
+ # @api public
120
+ def empty?
121
+ @_now.empty?
122
+ end
123
+
124
+ # @since 0.10.8
125
+ # @api public
126
+ def to_hash
127
+ @_now.dup
128
+ end
129
+
130
+ def length
131
+ @_now.length
132
+ end
133
+ alias_method :size, :length
134
+
135
+ # @since 0.10.8
136
+ # @api public
137
+ def to_s
138
+ @_now.to_s
139
+ end
140
+
141
+ # @since 0.10.8
142
+ # @api public
143
+ def error=(message)
144
+ self[:error] = message
145
+ end
146
+
147
+ # @since 0.10.8
148
+ # @api public
149
+ def error
150
+ self[:error]
151
+ end
152
+
153
+ # @since 0.10.8
154
+ # @api public
155
+ def notice=(message)
156
+ self[:notice] = message
157
+ end
158
+
159
+ # @since 0.10.8
160
+ # @api public
161
+ def notice
162
+ self[:notice]
163
+ end
164
+
165
+ # @since 0.10.8
166
+ # @api public
167
+ def success=(message)
168
+ self[:success] = message
169
+ end
170
+
171
+ # @since 0.10.8
172
+ # @api public
173
+ def success
174
+ self[:success]
175
+ end
176
+ end # Storage
177
+
178
+ module Helpers
179
+ ###
180
+ # Overloads the existing redirect helper in-order to provide support for
181
+ # flash messages.
182
+ #
183
+ # @overload redirect(url)
184
+ # @param [String] url
185
+ #
186
+ # @overload redirect(url, status_code)
187
+ # @param [String] url
188
+ # @param [Fixnum] status_code
189
+ #
190
+ # @overload redirect(url, status_code, flash_messages)
191
+ # @param [String] url
192
+ # @param [Fixnum] status_code
193
+ # @param [Hash] flash_messages
194
+ #
195
+ # @overload redirect(url, flash_messages)
196
+ # @param [String] url
197
+ # @param [Hash] flash_messages
198
+ #
199
+ # @example
200
+ # redirect(dashboard, success: :user_created)
201
+ # redirect(new_location, 301, notice: 'This page has moved. Please update your bookmarks!!')
202
+ #
203
+ # @since 0.10.8
204
+ # @api public
205
+ def redirect(url, *args)
206
+ flashes = args.extract_options!
207
+
208
+ flashes.each do |type, message|
209
+ message = I18n.translate(message) if message.is_a?(Symbol) && defined?(I18n)
210
+ flash[type] = message
211
+ end
212
+
213
+ super(url, args)
214
+ end
215
+ alias_method :redirect_to, :redirect
216
+
217
+ ###
218
+ # Returns the flash storage object.
219
+ #
220
+ # @return [Storage]
221
+ #
222
+ # @since 0.10.8
223
+ # @api public
224
+ def flash
225
+ @_flash ||= Storage.new(env['rack.session'] ? session[:_flash] : {})
226
+ end
227
+ end
228
+ end
229
+ end