Every repository with this icon (
Every repository with this icon (
No gems have been built for this project yet.
tree c5a8f980a605c76015c039ede92c05dcebd51eaf
parent 35aec621a19c6d4b2250919ef9707bb69336cd8d
| name | age | message | |
|---|---|---|---|
| |
.gitignore | Fri Nov 07 19:10:01 -0800 2008 | [pete] |
| |
README.rdoc | Thu Jun 19 09:59:34 -0700 2008 | [automatthew] |
| |
Rakefile | Thu Nov 06 20:09:32 -0800 2008 | [automatthew] |
| |
app/ | Thu Sep 18 11:55:21 -0700 2008 | [ab5tract] |
| |
bin/ | Thu Nov 06 21:28:53 -0800 2008 | [Pete Elmore] |
| |
doc/ | Fri Nov 07 18:49:53 -0800 2008 | [dyoder] |
| |
lib/ | Sun Nov 09 03:19:54 -0800 2008 | [dyoder] |
| |
samples/ | Sun Nov 02 10:32:09 -0800 2008 | [dyoder] |
| |
verify/ | Wed Sep 24 15:54:49 -0700 2008 | [automatthew] |
| |
waves.gemspec | Fri Oct 03 20:42:10 -0700 2008 | [automatthew] |
Waves
An open source framework for building web-applications with Ruby.
Waves is … Full-featured and thread-safe. Compact and extensible. Configuration and convention. RESTful but also Magical (very important).
Waves is powered by … Rack and Mongrel (HTTP server), Sequel or Filebase (storage), AutoCode (code reloading), LiveConsole (hot patching).
Links
- {Web Site}[http://rubywaves.com/]
- {Tutorial}[http://rubywaves.com/tutorial]
- {Contributors}[http://rubywaves.com/credits]
- {Source}[http://github.com/dyoder/waves]
- {Issue tracker}[http://waves.lighthouseapp.com]
- {Mailing List}[http://groups.google.com/group/rubywaves/]
- {RubyForge}[http://rubyforge.org/projects/waves/]
- {RDoc}[http://waves.rubyforge.org/]
Bootstrap!
Get Waves
# latest release from Rubyforge gem install waves # relatively recent gem build from master on GitHub gem install dyoder-waves --source=http://gems.github.com # get the framework source git clone git://github.com/dyoder/waves.git cd waves rake setup # install gem dependencies needed to work from source
Generate an application
# working from gems waves ~/dev/web/killer_app # working from source ./bin/waves ~/dev/web/killer_app
This generates a default application in the target directory. The application module’s name is the constant-cased version of the target directory basename, in this case KillerApp.
Configure basic settings
Configure your database connection using the database attribute in configurations/development.rb. The default ORM is currently Sequel, but there are other ORM layers in the works. The value of database is used with {Sequel.connect}[http://sequel.rubyforge.org/classes/Sequel.html#M000069]. Sequel’s current documentation seems to favor a URL-style argument, but we have been getting along fine with a hash.
# With the Sequel sqlite adapter, the :database parameter is read as a path # relative to the application root. database :adapter => 'sqlite', :database => 'killer_app.db'
Create the initial db schema. You can create a {Sequel migration}[http://sequel.rubyforge.org/classes/Sequel/Migration.html] with:
rake schema:migration name=users vi schema/migrations/001_users.rb
And you can run migrations with:
rake schema:migrate # or with a version number rake schema:migrate version=1
Mappings
Mappings are the Waves equivalent to routes. An individual mapping consists of a request-matching construct and an arbitrary block. When a request matches a mapping, Waves runs that block. In the simplest case, you do all the response work in the block, a la {Sinatra}[http://sinatrarb.com/Home]. The standard Waves application also offers an MVC infrastructure, with a silent R for Resource.
An application’s mappings live in configurations/mapping.rb. The generated default mixes in some RESTy mappings as a helpful starter:
- Waves::Mapping::PrettyUrls::RestRules
- Waves::Mapping::PrettyUrls::GetRules
Here’s an example of a mapping adapted from GetRules:
# define some regexes
model_regex = '([\w\-]+)'
name_regex = '([\w\-\_\.\+\@]+)';
# display the given resource for the given model
path %r{^/#{model_regex}/#{name_regex}/?$}, :method => :get do | model, name |
resource( model ) do
controller { find( name ) } | view { |data| show( model => data ) }
end
end
For convenience, we defined regexes to match the model and name components of a path. The path method registers a block for use with requests where the path matches the supplied regex and where the HTTP method is GET. The parameters passed to the block are the MatchData captures, i.e. the strings caught by model_regex and name_regex. Note that you can supply strings instead of regexes to match exact text. There is also a url method for matching against the entire URL.
So a GET to "/user/vyvyan", for example, will pass "user" and "vyvyan" to the block as the model and name parameters, respectively.
The resource method uses its argument to determine which controller and view will be instantiated for work done in its block. Thus using the example above, we instantiate KillerApp::Controllers::User when we call controller and KillerApp::Views::User when we call view.
The "|" character, as seen between the controller and view invocations, is a method that causes the result of the controller block to be passed into the view block. Thus, in the controller block, an instance of Controllers::User calls its find method with "vyvyan" as the argument. The resulting object is passed to an instance of Views::User, which calls show( "user" => <some user object>).
When undefined methods are called on a View, it attempts to render a template named after the method, with the method argument passed into the renderer as instance variables. In the present example, the view will try to render templates/user/show.mab (or show.erb), providing it with @user = <the user object>. You can, of course, define methods in the View to override this.
You can also register before, after, wrap, and always mappings, with the same flexibility in matching requests. The handle method registers exception handling blocks, matching the exception class as well as the usual request attributes.
For more complete documentation, see Waves::Mapping.
Running an application
cd killer_app # defaults to running on 127.0.0.1:3000, using the development config, not daemonized. waves-server -h 0.0.0.0 -p 3001 -c production --daemon
There are also rake tasks for running a cluster:
rake cluster:start mode=production # will read the Production config to determine which ports.
You can work in an irb-based console:
waves-console # or bin/waves-console
Where the Wavy Things Are
A Waves application consists of a Ruby module structured with internal namespaces. Thus:
KillerApp::Configurations KillerApp::Controllers KillerApp::Helpers KillerApp::Models KillerApp::Views
As you might have guessed, the working classes live in these namespaces. E.g. KillerApp::Models::User.
The otherwise harsh birth and life of these working classes is softened by {AutoCode}[http://autocode.rubyforge.org/], a sort of mini-Industrial Revolution for Ruby constants. The Waves framework uses AutoCode to automatically generate controllers, models, views, etc. the first time each constant is needed by the application. Waves looks for a file in a path that corresponds to the namespaced constant name. If such exists, it gets loaded. If not, Waves creates the class or module from sensible defaults.
For example, when a Waves application encounters KillerApp::Views::MonkeyShines for the first time, it tries to load it from ./views/monkey_shines.rb. If that file does not exist, the app creates KillerApp::Views::MonkeyShines as a dupe of Waves::Views::Base.
The result is that you only need to define models, views, etc. when the default behavior stops meeting your needs.
Directory structure
./
bin/
waves-console
waves-server
configurations/ # auto_load defined for Mapping; (auto_load || auto_create) anything else
controllers/ # (auto_load || auto_create)
helpers/ # (auto_load || auto_create)
lib/
application.rb # Application requires and includes, plus your configuration needs.
tasks/ # .rb and .rake files in here are automatically required by the main Rakefile
models/ # (auto_load || auto_create)
schema/
migrations/
startup.rb # Framework setup. Don't touch.
templates/ # Views expect templates to live here.
views/ # (auto_load || auto_create)
Web Server
You can run on any {Rack-supported Web server}[], including Thin and Mongrel. Just edit your configuration file, like you did for your database settings(configurations/development.rb) and change the <tt>handler parameter. The default is Mongrel. For example, to switch to Thin:
handler ::Rack::Handler::Thin, :Host => host, :Port => port
In addition, you can also configure your Rack application the same way. Just edit the application parameter:
application do
use ::Rack::ShowExceptions
use Rack::CommonLogger
run ::Waves::Dispatchers::Default.new
end




