Padrino

Padrino 0.11.0 Released - Padrino Lives!

The Padrino team is very pleased to finally be able to announce the 0.11.0 release of the Padrino Framework! We have been working on this release for almost a year now and we have had dozens of contributors helping us stabilize Padrino. We know our release cycle got out whack and this version took too long to release. We all take accountability for that and will work to pick up release momentum and release patch and minor versions more often.

Since our 0.10.7 release, development on Padrino has been moving forward very actively and as such this is probably our biggest release in terms of code modified and issues resolved that we have had in years. We are very proud of this release which includes several major improvements:

1) Totally Redesigned Admin 2) New brand identity on the way 3) Upgraded Sinatra and http_router 4) CSRF Form Protection 5) ActiveSupport::SafeBuffer 6) New Rakefile format 7) Gemified Apps 8) Performance Tools 9) App Namespacing 10) Project Modules 11) Optimized Reloader

and a lot more changes! In the full post below, we will take you through a tour of the biggest changes in this release (for a more compact view, see our changelog).

Redesigned Admin

We have introduced a number of exciting improvements to admin in this release. First, with the help of @WaYdotNET, we have completely rewritten the admin interface front-end. The new front-end uses bootstrap, font-awesome and jQuery. A few commits: 1, 2

This snowballed into a huge team effort so thanks to everyone involved @WaYdotNET, @DAddYE, @dariocravero), @ujifgc, @tyabe and several others! Here’s a few screenshots of our brand new admin pages:

" "

See more images in the Padrino Admin Album! Note that the new Padrino Admin has a responsive design that behaves well on tablets and mobile devices. Now you can even manage your admin data from your iPad!

There were also several additional fixes for admin listed below:

New brand identity on the way

We have started to rebrand ourselves, thanks to @tomatuxtemple we are getting there!.. Welcome the new logo:

The new web experience is just around the corner too, so keep your eyes and ears wide open!

Upgraded Sinatra and http_router

Sinatra 1.4 was just released recently, and we have full support for Sinatra 1.4.X in this release. Commits: 1, 2, 3, 4, 5

We have also upgraded to the latest http_router 0.11 to address many thread-safety issues and overall performance improvements.

Thanks to @DAddYE for putting together the http_router upgrade to 0.11. Commits: 1

CSRF Protection

Padrino now supports CSRF protection out of the box to enable additional security protection against unauthorized commands being sent to a Padrino application.

Thanks to @skade and @dariocravero for working together to implement this security feature. Commits: 1, 2, 3, 4, 5

ActiveSupport::SafeBuffer

In Padrino 0.11.0, we have begun work on improving the security of Padrino out of the box. We all take app security very seriously, and after much discussion decided to introduce a SafeBuffer into Padrino. This will help protect users against XSS (Cross-site Scripting) attacks.

This change switches all rendering to use SafeBuffer instead of a raw string. All strings returned from #render are considered escaped. Strings can be marked safe for concatenation using String#html_safe, which turns returns the String as a SafeBuffer.

All helpers have been ported over to use SafeBuffers. The changes follow one general rule: all tag helpers like tag and content_tag escape everything by default while block helpers like content_for and form_for assume that the given content is already escaped.

If you are generating HTML in your helpers, you should now make sure that you call html_safe on the result, so that the HTML is not automatically escaped:

def my_helper
  "<p>hello!</p>".html_safe
end

Thanks to @skade for proposing and putting this together! See commits here: 1, 2, 3, 4

This is a direct port of the functionality present in Rails, so thanks to the whole Rails team as well.

New Rakefile format

Another source of frustration for users was the missing Rakefile: now, every new project has one by default. `padrino rake` still continues to work, but bare `rake` works just as nice as well. Also, the Rakefile format has changed: instead of implicitly loading rake tasks that fit your environment, this is now explicit and looks like this:

require 'padrino-core/cli/rake'
PadrinoTasks.use(:sequel)
PadrinoTasks.use(:database)
PadrinoTasks.init

This makes it easier to replace tasks you don’t want to use and leads to less guessing by the framework. Don't like our database tasks? Just erase that line. Want to use them again? Just put it back in.

Old Rakefiles still work, but will emit a very visible warning on how to change your Rakefile to the new format. Thanks to @skade for putting this together!

Gemified Apps

An often requested feature for Padrino is the ability to easily package a Padrino application as a gem. We have now baked this right into the project generator. If you want to generate an application for use as a gem, we will automatically generate the gem and project structure for you! Simply add the --gem flag when generating a project:

padrino g project my_gemified_app --gem

This will generate a Padrino project within the context of a gem structure for you automatically. Now you can publish your Padrino apps as standalone gems with ease. After generation, see the README for more information about how to mount your gemified into Padrino projects.

A gemified project can be started and used like any other padrino project from its root path:

padrino start

But also be included into another project using the Gemfile. For development, you can use the :path option and the project will also be reloaded:

gem 'my_gemified_app' #, :path => /path/to/my_gemified_app

You can mount apps from other projects like so:

Padrino.mount('MyFancyApp::App', :app_file => MyGemifiedApp.root("my_fancy_app", "app.rb")).to('/my_fancy_app')

This is an exciting step for Padrino and creating truly standalone and modular applications that can be easily installed, setup and mounted into an existing Project. We have more plans for this as we approach towards 1.0.

Nothing keeps you from generating your main project as gemified project: there is nothing special about them, gemified projects behave like normal projects with some additions.

Thanks to @skade for putting this together! See commits here: 1, 2, 3, 4, 5

Performance Tools

In this release, we have also introduced a padrino-performance gem optionally included as part of your Padrino application. Simply add padrino-performance to your Gemfile. You can use the performance gem to check for well-know errors like multiple loaded json libraries on the console with:

bundle exec padrino-performance -j -- bundle exec padrino console

or profile the memory for your application:

bundle exec padrino-performance -m -- bundle exec padrino start

This represents the first step for our built-in memory and performance profiler within Padrino. This will get more love as we approach and move into our 1.0 release. We take performance and memory usage very seriously and are always striving to keep Padrino as lightweight as possible in line with our fast Sinatra foundations.

Thanks to @skade and @dariocravero for working together to get this to a solid place. You can find more details about this on the README and PR

App Namespacing

In addition to supporting gemified Padrino application, we have also taken another step towards modular design by introducing app namespacing. In the past, if a Padrino project was generated with the name “sample_blog”, then the application name would just be SampleBlog.

Starting with 0.11.0, generated project now have namespaced apps within a module. For example, if you generate a Padrino project named “sample_blog” with:

padrino g project sample_blog --orm activerecord

The primary app file will still be located in “app/app.rb” but the class will be SampleBlog::App. Similarly, everything else has been changed to support the namespacing to allow a project to be roughly self-contained within a single namespace.

One caveat is that to avoid any issues with various ORMs, models are not generated within the app namespace. Models will be continued to be generated outside of any namespace for simplicity.

Thanks to @achiu and Thanks to @skade for working together to finalize this and make this compatible with the new app gem support introduced as well.

Project Modules

Along with gemified apps, a new feature entered padrino-core: Project Modules. Those allow projects to live somewhere else then the applications root path and are a simple, yet powerful way of modularization. Project modules are tracked by the reloader and thus easy to use during development. A project module for a gemified app looks like this:

require 'padrino-core'
module GemifiedProject
  extend Padrino::Module
  gem! "gemified_project"
end

A project module will have its own root, so if you want to safely generate a path inside a gemified app, you should use the project module instead of Padrino:

GemifiedProject.root("config", "database.rb")

Project Modules, like Padrino have dependency_paths to play around with that are tracked by the reloader:

GemifiedProject.dependency_paths << "#{MyModule.root}/uploaders/*.rb"

The nice thing is that gem! is only a helper that indicates that this module should be loaded from a gem, along with proper tracking of the gems root path. You can also set up your own project module by hand, if you want to use some other form of organization. Just set the root correctly:

module MyProject
  extend Padrino::Module
  self.root = "/my/fixed/folder"
end

You can use the Module for project namespacing, if you want to:

module MyProject
  class MyModel
  end
end

Optimized Reloader

As many of you might know, the Padrino development reloader has been a common point of frustration and trouble for us. There is still a ways to go and we have some plans on how to replace the reloader for 1.0. Still, in 0.10.7, the reloader would in certain cases for large projects become increasingly slow. In extreme cases, reloading could take as long as 10+ seconds.

Several people helped us track this down and the reloader is substantially faster in this release. The primary fix was thanks to @dcu who helped us clean up our traversal of object space and substantially speed of the reloader in extreme cases. commit. We also fixed a thread-safety issue thanks to @udzura. Thanks guys!

Upgraded Components

Several updated components in this release:

We are committed to keeping our support components up to date. We can always use help so pull requests welcome!

Mailer

  • Lazy load mail gem for 20% padrino bootup speed improvement. commit (Thanks @ujifgc)
  • Upgrade to mail gem 2.5.3 to fix security vulnerabilities. commit
  • Refactor to cleanup and DRY code. commit (Thanks @Ortuna)

Logging

  • Fix Padrino.logger thread safety issues. commits: 1, 2, 3 (Thanks @sgonyea)
  • Add colorize_logging option. commit (Thanks @tyabe).
  • Display seconds instead of milliseconds. commit (Thanks @muxcmux)

Helpers

Cache Parser

We have also added a parser strategy pluggable interface for the padrino-cache. Now, you can select how the cache data is serialized into your cache store of choice. By default, we now store the data as plain text unless otherwise specified.

Example:

Padrino.cache = Padrino::Cache::File.new(...)
Padrino.cache.parser # => Padrino::Cache::Parser:Plain
Padrino.cache.parser = :marshal

Or you can write your own:

require 'oj'
module PadrinoJSON
  def self.encode(code)
    Oj.dump(code)
  end
  def self.decode(code)
    Oj.load(code)
  end
end

Finally you can load your strategy:

Padrino.cache.parser = PadrinoJSON

Thanks to @DAddYE for putting the parsing strategy system into place. commit

Bug Fixes

Lots of bug fixes and other changes in this release, see our changelog for a full rundown.

Explicit by default

A notable change comes in the philosophy of the framework: Instead of guessing application and task locations based on your bundle and project setup, Padrino will now use an explicit version (like setting the :app_file parameter for Padrino.mount and using PadrinoTasks.use in Rakefiles). This makes it far easier for users to replace them and makes it clearer what gets loaded and what doesn't. It also avoids frustrating mis-guesses by the framework. The old ways will still work for quite a while, but we believe that less magic is the way to go in the future. This is no API change, the underlying API was always there, its just used in another way.

Summary

As we mentioned, this is probably one of the bigger releases we have had in a long time, but we will keep the momentum moving and probably be out with a 0.11.1 release in the next couple weeks. Please let us know if you run into any problems (especially when upgrading from 0.10.X).

There are a lot of people that have made this release happen. Thanks to @skade, @dariocravero, and @ujifgc from our core team for doing a lot of the contributions towards 0.11.0.

Special thanks to @wikimatze for cleaning up our docs and comments all over our framework and for putting together an awesome Padrino book that helps people learn how to use Padrino. Also special thanks to @postmodern for helping us out recently especially when it comes to security, @WaYdotNET for being a long time contributor plus helping redesign admin and @Ortuna for helping us to refactor and clean up our codebase. As always, Padrino 0.11.0 would not be possible without the support of Konstantin Haase and everyone else involved in Sinatra. Thanks to all of our contributors.

That concludes the changelog for this release. As always if you want to keep up with Padrino updates, be sure to follow us on twitter: @padrinorb, join us on IRC at “#padrino” on freenode or open an issue on GitHub.

Contribute

Please report any issues you encounter with this release! We are working very actively on Padrino and want to make the framework as stable and reliable as possible. That concludes the changelog for this release. As always if you want to keep up with Padrino updates, be sure to follow us on twitter: @padrinorb, join us on IRC at “#padrino” on freenode, open an issue, or discuss on gitter.


comments powered by Disqus