dyoder-waves 0.7.3 → 0.7.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.
- data/app/bin/waves-console +1 -0
- data/app/bin/waves-server +1 -0
- data/app/configurations/development.rb.erb +5 -6
- data/app/configurations/mapping.rb.erb +1 -2
- data/app/configurations/production.rb.erb +2 -2
- data/app/controllers/.gitignore +0 -0
- data/app/doc/.gitignore +0 -0
- data/app/helpers/.gitignore +0 -0
- data/app/lib/application.rb.erb +4 -2
- data/app/lib/tasks/.gitignore +0 -0
- data/app/log/.gitignore +0 -0
- data/app/models/.gitignore +0 -0
- data/app/public/css/.gitignore +0 -0
- data/app/public/flash/.gitignore +0 -0
- data/app/public/images/.gitignore +0 -0
- data/app/public/javascript/.gitignore +0 -0
- data/app/schema/migrations/.gitignore +0 -0
- data/app/tmp/sessions/.gitignore +0 -0
- data/app/views/.gitignore +0 -0
- data/bin/waves +29 -46
- data/bin/waves-console +1 -1
- data/bin/waves-server +1 -1
- data/lib/commands/waves-console.rb +0 -3
- data/lib/controllers/base.rb +11 -0
- data/lib/controllers/mixin.rb +39 -32
- data/lib/dispatchers/base.rb +37 -22
- data/lib/dispatchers/default.rb +25 -11
- data/lib/foundations/default.rb +6 -8
- data/lib/foundations/simple.rb +13 -0
- data/lib/helpers/asset_helper.rb +67 -0
- data/lib/helpers/common.rb +4 -0
- data/lib/helpers/default.rb +13 -0
- data/lib/helpers/form.rb +1 -0
- data/lib/helpers/number_helper.rb +25 -0
- data/lib/helpers/tag_helper.rb +58 -0
- data/lib/helpers/url_helper.rb +77 -0
- data/lib/layers/default_errors.rb +7 -5
- data/lib/layers/mvc.rb +54 -0
- data/lib/layers/orm/active_record.rb +93 -0
- data/lib/layers/orm/active_record/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/active_record/tasks/generate.rb +28 -0
- data/lib/layers/orm/active_record/tasks/schema.rb +22 -0
- data/lib/layers/orm/data_mapper.rb +38 -0
- data/lib/layers/orm/filebase.rb +22 -0
- data/lib/layers/orm/migration.rb +79 -0
- data/lib/layers/orm/sequel.rb +86 -0
- data/lib/layers/orm/sequel/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/sequel/tasks/generate.rb +28 -0
- data/lib/layers/orm/sequel/tasks/schema.rb +16 -0
- data/lib/layers/simple.rb +35 -0
- data/lib/layers/simple_errors.rb +11 -5
- data/lib/mapping/mapping.rb +61 -24
- data/lib/mapping/pretty_urls.rb +5 -3
- data/lib/renderers/erubis.rb +3 -1
- data/lib/renderers/mixin.rb +1 -4
- data/lib/runtime/application.rb +12 -8
- data/lib/runtime/blackboard.rb +57 -0
- data/lib/runtime/configuration.rb +60 -55
- data/lib/runtime/logger.rb +8 -1
- data/lib/runtime/request.rb +5 -4
- data/lib/runtime/response.rb +3 -3
- data/lib/runtime/response_mixin.rb +3 -0
- data/lib/runtime/response_proxy.rb +4 -1
- data/lib/runtime/server.rb +18 -5
- data/lib/runtime/session.rb +20 -10
- data/lib/tasks/cluster.rb +2 -1
- data/lib/tasks/generate.rb +76 -11
- data/lib/utilities/hash.rb +31 -0
- data/lib/utilities/inflect.rb +86 -170
- data/lib/utilities/inflect/english.rb +84 -0
- data/lib/utilities/integer.rb +23 -16
- data/lib/utilities/module.rb +19 -15
- data/lib/utilities/object.rb +22 -14
- data/lib/utilities/proc.rb +13 -6
- data/lib/utilities/string.rb +58 -44
- data/lib/utilities/symbol.rb +4 -1
- data/lib/views/base.rb +9 -0
- data/lib/views/mixin.rb +3 -1
- data/lib/waves.rb +15 -13
- metadata +50 -25
- data/lib/utilities/kernel.rb +0 -34
- data/lib/verify/mapping.rb +0 -29
- data/lib/verify/request.rb +0 -40
@@ -0,0 +1,28 @@
|
|
1
|
+
namespace :generate do
|
2
|
+
|
3
|
+
desc 'Generate an ActiveRecord model, with name=<name>'
|
4
|
+
task :model do |task|
|
5
|
+
name = ENV['name']
|
6
|
+
model_name = name.camel_case
|
7
|
+
raise "Cannot generate Default yet" if model_name == 'Default'
|
8
|
+
|
9
|
+
filename = File.expand_path "models/#{name}.rb"
|
10
|
+
if File.exist?(filename)
|
11
|
+
$stderr.puts "#{filename} already exists"
|
12
|
+
exit
|
13
|
+
end
|
14
|
+
|
15
|
+
model = <<TEXT
|
16
|
+
module #{Waves.application.name}
|
17
|
+
module Models
|
18
|
+
class #{model_name} < Default
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
TEXT
|
24
|
+
|
25
|
+
File.write( filename, model )
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../../migration"
|
2
|
+
|
3
|
+
namespace :schema do
|
4
|
+
|
5
|
+
desc "Create ActiveRecord migration with name=<name>"
|
6
|
+
task :migration do |task|
|
7
|
+
Waves::Layers::ORM.create_migration_for(ActiveRecord)
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Performs ActiveRecord migrations to version=<version>"
|
11
|
+
task :migrate => :connect do |task|
|
12
|
+
version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
|
13
|
+
ActiveRecord::Migrator.migrate(Waves::Layers::ORM.migration_directory, version)
|
14
|
+
end
|
15
|
+
|
16
|
+
task :connect do
|
17
|
+
Waves.application.database
|
18
|
+
ActiveRecord::Base.logger = Logger.new($stdout)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
gem 'dm-core', '=0.9.0'
|
2
|
+
|
3
|
+
require 'data_mapper'
|
4
|
+
|
5
|
+
module Waves
|
6
|
+
module Layers
|
7
|
+
module ORM
|
8
|
+
|
9
|
+
# Work in Progress
|
10
|
+
module DataMapper
|
11
|
+
|
12
|
+
def self.included(app)
|
13
|
+
|
14
|
+
def app.database
|
15
|
+
@adapter ||= ::DataMapper.setup(:main_repository, config.database[:database])
|
16
|
+
end
|
17
|
+
|
18
|
+
app.auto_eval :Models do
|
19
|
+
auto_load true, :directories => [:models]
|
20
|
+
end
|
21
|
+
|
22
|
+
app.auto_eval :Configurations do
|
23
|
+
auto_eval :Mapping do
|
24
|
+
before true do
|
25
|
+
app.database #force adapter init if not already done
|
26
|
+
::DataMapper::Repository.context.push(::DataMapper::Repository.new(:main_repository))
|
27
|
+
end
|
28
|
+
always true do
|
29
|
+
::DataMapper::Repository.context.pop
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Waves
|
2
|
+
module Layers
|
3
|
+
module ORM
|
4
|
+
|
5
|
+
# Work in Progress
|
6
|
+
module Filebase
|
7
|
+
|
8
|
+
def self.included(app)
|
9
|
+
app.module_eval do
|
10
|
+
auto_eval( :Models ) do
|
11
|
+
auto_eval( true ) { include Filebase::Model[ :db / self.name.snake_case ] }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Waves
|
2
|
+
module Layers
|
3
|
+
|
4
|
+
# Helper methods to establish inter-ORM standards
|
5
|
+
module ORM
|
6
|
+
|
7
|
+
# Glob pattern
|
8
|
+
MIGRATION_FILE_PATTERN = '[0-9][0-9][0-9]_*.rb'.freeze
|
9
|
+
|
10
|
+
def self.create_migration_for(orm)
|
11
|
+
source = migration_template(orm.to_s.snake_case, ENV['template'])
|
12
|
+
destination = migration_destination(ENV['name'])
|
13
|
+
migration_name = migration_name(ENV['name'])
|
14
|
+
|
15
|
+
context = {:class_name => migration_name.camel_case}
|
16
|
+
|
17
|
+
write_migration(context, source, destination)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Where Waves keeps its migration files
|
21
|
+
def self.migration_directory
|
22
|
+
:schema / :migrations
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns any found migration files in the supplied directory.
|
26
|
+
def self.migration_files(range = nil)
|
27
|
+
pattern = migration_directory / MIGRATION_FILE_PATTERN
|
28
|
+
files = Dir[pattern].inject([]) do |m, path|
|
29
|
+
m[File.basename(path).to_i] = path
|
30
|
+
m
|
31
|
+
end
|
32
|
+
filtered = range ? files[range] : files
|
33
|
+
filtered ? filtered.compact : []
|
34
|
+
end
|
35
|
+
|
36
|
+
# Use the supplied version number or determine the next in sequence
|
37
|
+
# based on the migration files in the migration directory
|
38
|
+
def self.next_migration_version
|
39
|
+
version = ENV['version'] || latest_migration_version
|
40
|
+
version.to_i + 1
|
41
|
+
end
|
42
|
+
|
43
|
+
# Uses the migration files in the migration directory to determine
|
44
|
+
# the highest numbered existing migration.
|
45
|
+
def self.latest_migration_version
|
46
|
+
l = migration_files.last
|
47
|
+
l ? File.basename(l).to_i : nil
|
48
|
+
end
|
49
|
+
|
50
|
+
# If the user doesn't pass a name, defaults to "migration"
|
51
|
+
def self.migration_name(name=nil)
|
52
|
+
name || 'migration'
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the path to the migration template file for the given ORM.
|
56
|
+
# <em>orm</em> can be a symbol or string
|
57
|
+
def self.migration_template(orm, name=nil)
|
58
|
+
file = ( name || 'empty' ) + '.rb.erb'
|
59
|
+
source = File.dirname(__FILE__) / orm / :migrations / file
|
60
|
+
end
|
61
|
+
|
62
|
+
# Given a migration name, returns the path of the file that would be created.
|
63
|
+
def self.migration_destination(name)
|
64
|
+
version = next_migration_version
|
65
|
+
migration_directory / "#{'%03d' % version}_#{migration_name(name)}.rb"
|
66
|
+
end
|
67
|
+
|
68
|
+
# Takes an assigns hash as the Erubis context. Keys in the hash become
|
69
|
+
# instance variable names.
|
70
|
+
def self.write_migration(context, source, destination)
|
71
|
+
code = Erubis::Eruby.new( File.read( source ) ).evaluate( context )
|
72
|
+
puts "Creating #{destination}"
|
73
|
+
File.write( destination, code )
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
gem 'sequel', '>= 2.0.0'
|
2
|
+
require 'sequel'
|
3
|
+
require "#{File.dirname(__FILE__)}/sequel/tasks/schema" if defined?(Rake)
|
4
|
+
require "#{File.dirname(__FILE__)}/sequel/tasks/generate" if defined?(Rake)
|
5
|
+
|
6
|
+
module Waves
|
7
|
+
module Layers
|
8
|
+
module ORM # :nodoc:
|
9
|
+
|
10
|
+
# Sets up the Sequel connection and configures AutoCode on Models, so that constants in that
|
11
|
+
# namespace get loaded from file or created as subclasses of Models::Default
|
12
|
+
module Sequel
|
13
|
+
|
14
|
+
# On inclusion, this module:
|
15
|
+
# - creates on the application module a database method that establishes the Sequel connection
|
16
|
+
# - arranges for autoloading/autocreation of missing constants in the Models namespace
|
17
|
+
# - defines Sequel-specific helper methods on Waves::Controllers::Base
|
18
|
+
#
|
19
|
+
# The controller helper methdods are:
|
20
|
+
# - all
|
21
|
+
# - find(name)
|
22
|
+
# - create
|
23
|
+
# - delete(name)
|
24
|
+
# - update(name)
|
25
|
+
#
|
26
|
+
def self.included(app)
|
27
|
+
|
28
|
+
def app.database ; @sequel ||= ::Sequel.open( config.database ) ; end
|
29
|
+
|
30
|
+
app.auto_create_module( :Models ) do
|
31
|
+
include AutoCode
|
32
|
+
auto_create_class :Default, ::Sequel::Model
|
33
|
+
auto_load :Default, :directories => [ :models ]
|
34
|
+
end
|
35
|
+
|
36
|
+
app.auto_eval :Models do
|
37
|
+
auto_create_class true, app::Models::Default
|
38
|
+
auto_load true, :directories => [ :models ]
|
39
|
+
# set the Sequel dataset based on the model class name
|
40
|
+
# note that this is not done for app::Models::Default, as it isn't
|
41
|
+
# supposed to represent a table
|
42
|
+
auto_eval true do
|
43
|
+
default = superclass.basename.snake_case.pluralize.intern
|
44
|
+
if @dataset && @dataset.opts[:from] != [ default ]
|
45
|
+
# don't clobber dataset from autoloaded file
|
46
|
+
else
|
47
|
+
set_dataset Waves.application.database[ basename.snake_case.pluralize.intern ]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
Waves::Controllers::Base.instance_eval do
|
53
|
+
include Waves::Layers::ORM::Sequel::ControllerMethods
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
# Mixed into Waves::Controllers::Base. Provides ORM-specific helper methods for model access.
|
59
|
+
module ControllerMethods
|
60
|
+
def all
|
61
|
+
model.all
|
62
|
+
end
|
63
|
+
|
64
|
+
def find( name )
|
65
|
+
model[ :name => name ] or not_found
|
66
|
+
end
|
67
|
+
|
68
|
+
def create
|
69
|
+
model.create( attributes )
|
70
|
+
end
|
71
|
+
|
72
|
+
def delete( name )
|
73
|
+
find( name ).destroy
|
74
|
+
end
|
75
|
+
|
76
|
+
def update( name )
|
77
|
+
instance = find( name )
|
78
|
+
instance.update_with_params( attributes )
|
79
|
+
instance
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
namespace :generate do
|
2
|
+
|
3
|
+
desc 'Generate a Sequel model, with name=<name>'
|
4
|
+
task :model do |task|
|
5
|
+
name = ENV['name']
|
6
|
+
model_name = name.camel_case
|
7
|
+
raise "Cannot generate Default yet" if model_name == 'Default'
|
8
|
+
|
9
|
+
filename = File.expand_path "models/#{name}.rb"
|
10
|
+
if File.exist?(filename)
|
11
|
+
$stderr.puts "#{filename} already exists"
|
12
|
+
exit
|
13
|
+
end
|
14
|
+
|
15
|
+
model = <<TEXT
|
16
|
+
module #{Waves.application.name}
|
17
|
+
module Models
|
18
|
+
class #{model_name} < Default
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
TEXT
|
24
|
+
|
25
|
+
File.write( filename, model )
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../../migration"
|
2
|
+
|
3
|
+
namespace :schema do
|
4
|
+
|
5
|
+
desc "Create a new Sequel Migration with name=<name>"
|
6
|
+
task :migration do |task|
|
7
|
+
Waves::Layers::ORM.create_migration_for(Sequel)
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Performs Sequel migrations to version=<version>"
|
11
|
+
task :migrate do |task|
|
12
|
+
version = ENV['version']; version = version.to_i unless version.nil?
|
13
|
+
Sequel::Migrator.apply( Waves.application.database, Waves::Layers::ORM.migration_directory , version )
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Waves
|
2
|
+
|
3
|
+
# Waves uses Layers to provide discrete, stackable, interchangeable bundles of functionality.
|
4
|
+
#
|
5
|
+
# Developers can make use of Layers by including them directly in a Waves application:
|
6
|
+
#
|
7
|
+
# module MyApp
|
8
|
+
# include SomeLayer
|
9
|
+
# end
|
10
|
+
module Layers
|
11
|
+
|
12
|
+
# Creates the Configurations namespace and establishes the standard autoload-or-autocreate
|
13
|
+
# rules.
|
14
|
+
module Simple
|
15
|
+
def self.included( app )
|
16
|
+
|
17
|
+
def app.config ; Waves.config ; end
|
18
|
+
def app.configurations ; self::Configurations ; end
|
19
|
+
|
20
|
+
app.instance_eval { include AutoCode }
|
21
|
+
|
22
|
+
app.auto_create_module( :Configurations ) do
|
23
|
+
include AutoCode
|
24
|
+
auto_create_class true, Waves::Configurations::Default
|
25
|
+
auto_load :Mapping, :directories => [:configurations]
|
26
|
+
auto_load true, :directories => [:configurations]
|
27
|
+
auto_eval :Mapping do
|
28
|
+
extend Waves::Mapping
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
data/lib/layers/simple_errors.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
module Waves
|
2
2
|
module Layers
|
3
|
+
# Configures Waves for minimal exception handling.
|
4
|
+
#
|
5
|
+
# For example,
|
6
|
+
# a NotFoundError results in response status of 404, with body text
|
7
|
+
# of "404 Not Found".
|
3
8
|
module SimpleErrors
|
4
9
|
|
5
10
|
def self.included( app )
|
6
11
|
|
7
|
-
app.
|
8
|
-
|
9
|
-
|
10
|
-
|
12
|
+
app.auto_eval :Configurations do
|
13
|
+
auto_eval :Mapping do
|
14
|
+
handle(Waves::Dispatchers::NotFoundError) do
|
15
|
+
response.status = 404; response.body = "404 Not Found"
|
16
|
+
end
|
11
17
|
end
|
12
|
-
|
13
18
|
end
|
19
|
+
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
data/lib/mapping/mapping.rb
CHANGED
@@ -1,11 +1,33 @@
|
|
1
1
|
module Waves
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
3
|
+
# Mappings in Waves are the interface between the request dispatcher and your
|
4
|
+
# application code. The dispatcher matches each request against the mappings
|
5
|
+
# to determine a primary action and to collect sets of before, after, wrap,
|
6
|
+
# and always actions. The dispatcher also looks for an exception handler
|
7
|
+
# registered in the mappings when attempting a rescue.
|
8
|
+
#
|
9
|
+
# Each mapping associates a block with a set of constraints. Mappings can be
|
10
|
+
# one of several types:
|
11
|
+
#
|
12
|
+
# - action (the actual request processing and response)
|
13
|
+
# - handle (exception handling)
|
14
|
+
# - before
|
15
|
+
# - after
|
16
|
+
# - wrap (registers its block as both a before and after action)
|
17
|
+
# - always (like an "ensure" clause in a rescue)
|
18
|
+
#
|
19
|
+
# Actions are registered using path, url, or map. The other types may be
|
20
|
+
# registered using methods named after the type.
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# The available constraints are:
|
24
|
+
#
|
25
|
+
# - a string or regexp that the path or url must match
|
26
|
+
# - parameters to match against the HTTP request headers and the Rack-specific variables (e.g. 'rack.url_scheme')
|
27
|
+
# - an additional hash reserved for settings not related to the Rack request (e.g. giving Rack handers special instructions for certain requests. See threaded? )
|
28
|
+
#
|
29
|
+
# The dispatcher evaluates mapping blocks in an instance of ResponseProxy,
|
30
|
+
# which provides access to foundational classes of a Waves application (i.e. controllers and views)
|
9
31
|
#
|
10
32
|
# == Examples
|
11
33
|
#
|
@@ -104,6 +126,7 @@ module Waves
|
|
104
126
|
end
|
105
127
|
|
106
128
|
# Similar to before, except it runs its actions after any matching +url+ or +path+ actions.
|
129
|
+
# Note that after methods will run even if an exception is thrown during processing.
|
107
130
|
def after( path, options = {}, &block )
|
108
131
|
if path.is_a? Hash
|
109
132
|
options = path
|
@@ -124,15 +147,26 @@ module Waves
|
|
124
147
|
filters[:after] << [ options, block ]
|
125
148
|
end
|
126
149
|
|
127
|
-
#
|
128
|
-
#
|
129
|
-
def
|
150
|
+
# Like after, but will run even when an exception is thrown. Exceptions in
|
151
|
+
# always mappings are simply logged and ignored.
|
152
|
+
def always( path, options = {}, &block )
|
130
153
|
if path.is_a? Hash
|
131
|
-
params = options
|
132
154
|
options = path
|
133
155
|
else
|
134
156
|
options[:path] = path
|
135
157
|
end
|
158
|
+
filters[:always] << [ options, block ]
|
159
|
+
end
|
160
|
+
|
161
|
+
# Maps a request to a block. Don't use this method directly unless you know what
|
162
|
+
# you're doing. Use +path+ or +url+ instead.
|
163
|
+
def map( path, options = {}, params = {}, &block )
|
164
|
+
case path
|
165
|
+
when Hash
|
166
|
+
params = options; options = path
|
167
|
+
when String
|
168
|
+
options[:path] = path
|
169
|
+
end
|
136
170
|
mapping << [ options, params, block ]
|
137
171
|
end
|
138
172
|
|
@@ -155,7 +189,7 @@ module Waves
|
|
155
189
|
def root( options = {}, params = {}, &block )
|
156
190
|
path( %r{^/?$}, options, params, &block )
|
157
191
|
end
|
158
|
-
|
192
|
+
|
159
193
|
# Maps an exception handler to a block.
|
160
194
|
def handle(exception, options = {}, &block )
|
161
195
|
handlers << [exception,options, block]
|
@@ -186,12 +220,12 @@ module Waves
|
|
186
220
|
end
|
187
221
|
return false
|
188
222
|
end
|
189
|
-
|
223
|
+
|
190
224
|
# Match the given request against the defined rules. This is typically only called
|
191
225
|
# by a dispatcher object, so you shouldn't typically use it directly.
|
192
226
|
def []( request )
|
193
227
|
|
194
|
-
rx = { :before => [], :after => [], :action => nil, :handlers => [] }
|
228
|
+
rx = { :before => [], :after => [], :always => [], :action => nil, :handlers => [] }
|
195
229
|
|
196
230
|
( filters[:before] + filters[:wrap] ).each do | options, function |
|
197
231
|
matches = match( request, options, function )
|
@@ -208,6 +242,11 @@ module Waves
|
|
208
242
|
rx[:after] << matches if matches
|
209
243
|
end
|
210
244
|
|
245
|
+
filters[:always].each do | options, function |
|
246
|
+
matches = match( request, options, function )
|
247
|
+
rx[:always] << matches if matches
|
248
|
+
end
|
249
|
+
|
211
250
|
handlers.each do | exception, options, function |
|
212
251
|
matches = match( request, options, function )
|
213
252
|
rx[:handlers] << matches.unshift(exception) if matches
|
@@ -218,35 +257,33 @@ module Waves
|
|
218
257
|
|
219
258
|
# Clear all mapping rules
|
220
259
|
def clear
|
221
|
-
@mapping = @filters = nil;
|
260
|
+
@mapping = @filters = @handlers = nil;
|
222
261
|
end
|
223
262
|
|
224
263
|
private
|
225
264
|
|
226
265
|
def mapping; @mapping ||= []; end
|
227
266
|
|
228
|
-
def filters; @filters ||= { :before => [], :after => [], :wrap => [] }; end
|
267
|
+
def filters; @filters ||= { :before => [], :after => [], :wrap => [], :always => [] }; end
|
229
268
|
|
230
269
|
def handlers; @handlers ||= []; end
|
231
270
|
|
232
271
|
def match ( request, options, function )
|
233
272
|
return nil unless satisfy( request, options )
|
234
|
-
if options[:path]
|
235
|
-
|
236
|
-
|
237
|
-
matches = options[:url].match( request.url )
|
238
|
-
end
|
273
|
+
return [ function, nil ] if ( options[:path] == true or options[:url] == true )
|
274
|
+
matches = options[:path].match( request.path ) if options[:path]
|
275
|
+
matches = options[:url].match( request.url ) if options[:url]
|
239
276
|
return [ function, matches ? matches[1..-1] : nil ]
|
240
277
|
end
|
241
278
|
|
242
279
|
def satisfy( request, options )
|
243
280
|
options.nil? or options.all? do |name,wanted|
|
244
|
-
|
245
|
-
|
246
|
-
( ( wanted.is_a?(Regexp)
|
247
|
-
got.to_s == wanted.to_s ) unless ( wanted.nil? or got.nil? )
|
281
|
+
return true if wanted == true
|
282
|
+
got = request.send( name ) rescue request.env[ ( name =~ /^rack\./ ) ? name.to_s.downcase : name.to_s.upcase ]
|
283
|
+
( ( wanted.is_a?(Regexp) and wanted.match( got.to_s ) ) or got.to_s == wanted.to_s ) unless ( wanted.nil? or got.nil? )
|
248
284
|
end
|
249
285
|
end
|
250
286
|
end
|
287
|
+
|
251
288
|
|
252
289
|
end
|