Padrino 0.10.0 - Routing Upgrades, Rbx and JRuby Support, and Minor Breaking

Roughly a month has went by since our last release and there have been several developments since then. Today, we are release our first minor point release in a while because we have introduced a breaking change to the way Padrino loads our rendering module.

This 0.10.0 release brings a couple new features such as enhanced route filter support, significantly faster routing engine, full compatibility with Rubinius and JRuby, bug fixes and several other improvements. The next releases coming in the pipeline are 0.10.1 (for Sinatra 1.3), 0.10.2 (for AS 3.1) and then a release candidate for our 1.0 release barring any major complications. Details for this release are below.

Rendering Module Changes

In this release, we have introduced a breaking change to the way Padrino loads the Padrino::Rendering module. Working with botanicus recently on an issue, we uncovered a problem with the auto-loading of our enhanced rendering module.

The issue is that any extension to Sinatra/Padrino that wishes to extend rendering was unable to load before our module. This produced situations where Padrino rendering is difficult to enhance with outside extensions. We have decided to remove the autoloading of Padrino::Rendering. For freshly generated applications, no action needs to be taken because Rendering will be included in the generated application.

For an existing application, all you need to do is add an explicit include to Padrino::Rendering:

# app/app.rb
class Demo < Padrino::Application
  register Padrino::Rendering # <= Add this line
  # ...
  register Padrino::Helper

on every application within a project. For those that are curious, the Padrino::Rendering module is the functionality that enhances “render” to auto-locate templates and adds support for I18n amongst a variety of other conveniences that makes template rendering much more powerful and convenient. If you are using render "index" in your code then you are using this module. Commit here.

Rubinius and JRuby Compatibility

This release also marks full support for Rubinius and JRuby, two of the upcoming stable ruby implementations gaining attention. As of this tweet, we are now 100% compatible with Rubinius and have tested full support for JRuby. Uchio Kondo, the official Japanese documentation maintainer for Padrino has also created an excellent guide for Running Padrino on JRuby which gets you started. Commits here, here, and here.

Routing Speed Improvements

Josh has enabled serious performance gains in http_router which has once again allowed Padrino to parallel Sinatra in performance even in an more advanced demo application. In all our benchmarks, Sinatra and Padrino are generally neck-in-neck:

# Benchmarks
System: Linux 2.6.18-xenU-ec2-v1.0
Processor: Intel(R) Xeon(R) CPU           E5430  @ 2.66GHz
Memory: 1740948 kB
Ruby: ruby 1.9.2p180 (2011-02-18 revision 30909) [i686-linux]
 padrino (0.10.0)
 rack (1.3.0)
 sinatra (1.2.6)
 rack (1.2.3)
 rails (3.0.8)
 camping (2.1)
 rack => 620.95 rps
 camping => 398.74 rps
 sinatra => 309.78 rps
 padrino => 302.64 rps
 merb => 291.43 rps
 rails => 122.37 rps

Commits here to upgrade http_router and take advantage of the optimizations. Thanks again to joshbuddy (Joshua Hull) of our core team for hacking on these upgrades!

Route Filters

An oft-requested feature is for enhanced route filters. While Sinatra does have basic support for filters, a heavy user will often find that it leaves things to be desired. Namely when dealing with namespaces and routes. Whereas before, a filter looks like this:

# app/controllers/example_controller.rb
DemoApp.controller :example do
  before "/example/*" do
    # Code here to be executed

  get :index do
    # ...

Now you can have a lot more options related to filters and they work much more intuitively thanks to Joshua (joshbuddy) and you can do:

# app/controllers/example_controller.rb
DemoApp.controller :example do
  # Based on a symbol
  before :index do
    # Code here to be executed

  # Based on a symbol, regexp and string all in one
  before :index, /main/, '/example' do
    # Code here to be executed

  # Also filter by excluding an action
  before :except => :index do
    # Code here to be executed

  get :index do
    # ...

This gives developers a lot more flexibility when running filters and enables much more selective execution in a convenient way. Great to have this feature available as part of our routing enhancements. Commits here and here.

Route Ordered Priority

This release has also added support for respecting route order in controllers and also allows the developer to specify certain routes as less or more “important” then others in the route recognition order. Consider two controllers, the first with a “catch-all” route that matches any URL and the second below in another controller that is very specific. This wouldn't work by default because the second endpoint would be eclipsed by the catch-all route and as such would not be accessible. To solve this, you can do the following:

# app/controllers/pages.rb
MyApp.controller :pages do
  # NOTE that this route is now marked as low priority
  get :show, :map => :map => '/*page', :priority => :low do
    "Catchall route"

# app/controllers/projects.rb
MyApp.controller :projects do
  get :index do
    "Important Index"

When setting a routes priority to :low, this route is then recognized in order lower then all “high” and “normal” priority routes. You are encouraged in cases where there is ambiguity, to mark key routes as :priority => :high or catch-all routes as :priority => :low in order to guarantee expected behavior.

Commit here.

Reloader Fixes

The reloader has been much improved in the last release, and we are continuing in that tradition improving the reloader again to be more robust in this release:

  • Better support for constant reloading commit
  • Fix Padrino::Reloader reloading also \$LOADED_FEATURES deps commit
  • Remove incomplete constants when require fails (Thanks bernerdschaefer) commit

There is also a new way to add files to the reloader manually using the prerequisites method:

# app/app.rb
MyApp.prerequisites << Padrino.root('my_app', 'custom_model.rb')

This will autoload those files and watch them for changes. Commit here.

Other changes and fixes

  • Adds support for the Ripple ORM (Thanks pepe) commit
  • Hungarian translations added (Thanks Kormány Zsolt) commit
  • Controller now supports conditions at multiple levels (Thanks bernerdschaefer) commit
  • Gemspecs and are now executable (Thanks botanicus): [commit, commit]
  • Add support for padrino s for starting the padrino server commit
  • Fix field generation for DataMapper commit
  • Fixes issue with DM length for strings commit
  • Fixes double loading for boot.rb in rake tasks commit
  • Cleanup padrino-core dependencies in support_lite commit
  • Bundler is now auto-loaded in our binaries commit
  • Adds access to “current_controller” as part of the public API commit
  • Changes DM instructions to recommend rake dm:auto:upgrade commit

Padrino 0.9.29 - Stability, compatibility and bug fix release

Today we are releasing Padrino 0.9.29, the latest in a series of stability and bug fix releases designed to bring us closer to the 0.10.0 release coinciding with the release of Sinatra 1.3! This release has several essential bug and compatibility fixes that ensure developers working with Padrino have a smooth experience. This release also might require a few changes due to a tweak in how session enabling works explained below.

The biggest changes are significant speed enhancements with our routing system, a complete rewrite of our development reloader, general core cleanup and Rake 0.9 and JRuby compatibility fixes. Read below for more details.

Upgrade Steps for 0.9.29

When upgrading to this latest release, you should take advantage of project-wide configurations and apply the following snippet to apps.rb:

# config/apps.rb
Padrino.configure_apps do
  enable :sessions
  # $ padrino rake gen
  # $ rake secret
  set :session_secret, "long secret key pasted here"

Adding this to the top of your app.rb will enable sessions in all applications within the project and use a secret session key to persist the session properly across all these apps. Make sure to run the ‘rake secret’ command and put the session key into the :session_secret setting. Not doing this can create session related issues in your project.

Major improvements to Development Reloading

Over the last few releases, we have been experiencing a number of issues with our development reloader. Certain files weren't detected or reloaded properly, the reloader would hang up during a reload, certain files would be unloaded causing exceptions, et al.

In this release, we have worked closely with several users experiencing issues and in many ways completely rewrote the development code reloading system. We think the reloader is much more stable now and this also means faster boot and reloading times as well because the new reloader has been greatly streamlined.

Thanks specifically to @daddye of our core team for addressing these problems in the rewrite. Commits here, here, and here. Let's not forget even more commits here, here and finally here. Big thanks to bernerdschaefer for his help debugging and patching the reloader as well!

Core Cleanup

In addition to the development reloader, we have also cleaned and refactored several other modules within padrino-core. In particular we have cleaned up and refactored our SupportLite, Padrino::Application, Gemfile generation, and the Padrino::Server:

  • Refactored and cleaned up Padrino::Server: commit
  • Removed old stuff from support_lite: commit
  • Cleanup Gemfile to simplify loading: commit
  • Cleanup support lite and improved compatiblity with jruby: commit

This cleanup is part of a larger effort as we work towards solidifying our internals.

Routing Speed Improvements

Our routing core http_router has been significantly optimized in the last few point versions for speed. We will be doing several benchmarks soon and will post them but for now suffice to say we have been making a lot of strides to make our routing even faster then before and this will be an ongoing effort. Thanks to Joshua Hull of our core team for creating probably the best Ruby request router available and it work for plain Sinatra too!

Truncate Words Helper

A new helper has been added called “truncate_words”. This is an alternative to the existing “truncate” method which shortens a string by characters, this helper shortens a string by words:

truncate_words("Once upon a time in a world far far away", :length => 4) => "Once upon a time..."

Commit is here and thanks to cearls for contributing this helper for us!

Better Dependency Handling

We have simplified dependency handling and the approach for adding new dependencies and load_paths to a Padrino application.

# config/boot.rb
  MyApp.load_paths << Padrino.root('app', 'observers')
  MyApp.dependencies << Padrino.root('other_app', 'controllers.rb')

Commits here and here.

Bug and Compatibility Fixes

  • Compatibility with CouchRest::Model 1.1: commit
  • Fix bug with render and local vars: commit
  • Honor / in Accept headers correctly – commit
  • Rake 0.9 Compatibility: commit
  • Rack::Flash now sweeps on every request by default: commit
  • Supports skipping Padrino::Render with constant: commit

  • Prev Page
  • Next Page