Padrino 0.12.0


2014-02-09 に Padrino のバージョン 0.12.0 がリリースされました。
公式ブログに[変更内容](http://www.padrinorb.com/blog/padrino-0-12-0-activesupport-4-rewritten-reloader-smarter-rendering-and-loads-more)と[移行ガイド](http://www.padrinorb.com/blog/upgrading-padrino-from-0-11-x-to-0-12-0-guide)がまとめられていますが、日本語で簡単に整理してみました。



## Ruby 1.8 のサポート廃止、Ruby 2.1.0 をサポート

Ruby 1.8 のサポートを廃止したことにより、
ActiveSupport 4 ( ActiveRecord 4 も ) が使用できるようになりました。

## レンダリングの改善

render メソッドが改善され、呼び出し元のコントローラと同名のディレクトリからテンプレートを探してくれるようになりました。

```ruby:app/controllers/pages_controller.rb
Sample::App.controllers :pages do
  get :index do
    # BEFORE
    render 'pages/show' # 明示的にパスを指定
    # AFTER
    render 'show'       # 'pages'ディレクトリから探してくれる
  end
end
```

テンプレートとレイアウトで別々のテンプレートエンジンが使える様になりました。
例えば、レイアウトは'haml'でありつつ、テンプレートは'erb'を使うとかができるようになりました。

content_tag にブロックを渡した時の動作が最適化され、評価結果が返るようになりました。


## テンプレートの改善

テンプレートエンジンに slim と haml を使っている場合、
`-` でコードの評価結果が出力されないようになりました。

```ruby
# app/helpers/application_helper.rb
def hello
  content_tag(:div) do
    content_tag(:p, 'hello')
  end
end

# app/views/index.slim
/ 評価結果が出力されない
- hello

/ 評価結果が出力される
= hello
```

`form_tag` や `field_set_tag` を使っていた場合は変更が必要になるので注意が必要です。
## リローダーの改善

規模が大きくなったアプリでもスムーズにリロードされるようになりました。
また、リロード中にエラーが起こりにくくなりました。

## キャッシュ機構のリプレース

キャッシュ機構のベースに [Moneta](https://github.com/minad/moneta)が 採用されました。

これにより、キャッシュストアの指定方法やキャッシュの設定・取得方法が変更となりました。

```ruby
# BEFORE
Padrino.cache = Padrino::Cache::Store::File.new(Padrino.root('tmp', app_name, 'cache')

# AFTER
Padrino.cache = Padrino::Cache.new(:File, :dir => Padrino.root('tmp', app_name.to_s, 'cache'))
```

```ruby
# BEFORE
MyProject::App.cache.set('val', 'test')
MyProject::App.cache.get('val') # => 'test'

# AFTER
MyProject::App.cache['val'] = 'test'
MyProject::App.cache['val'] # => 'test'
```

ファイルストアを使用している場合、0.12.0 へ移行の際にはキャッシュファイルの削除が必要です。

詳細は[ここ](https://github.com/padrino/padrino-framework/blob/master/padrino-cache/README.rdoc)で確認してください。

## アプリのマウントでカスケードをサポート

以下のようなルーティングをもつ2つのアプリがあったとします。
(`/foo` に対するアクセスを、基本的には App2 で捌きたいんだけど、一部は App で扱いたい)

```ruby:app/controllers/foo.rb
Sample::App.controllers :foo do
  get(:other) { 'this is app.' }
end
```
```ruby:app2/app.rb
module Sample
  class App2 < Padrino::Application
    get(:index) { 'this is app2' }
  end
end
```
```ruby:config/apps.rb
Padrino.mount('Sample1::App2', app_file: Padrino.root('app2/app.rb'), cascade: true).to('/foo')
Padrino.mount('Sample1::App',  app_file: Padrino.root('app/app.rb')).to('/')
```

`config/apps.rb` で cascade オプションに true を渡すことで、
`/foo` で始まるパスが App2 で見つからない場合は App のルーティングも探索するようになります。

デフォルトでは cascade は false となっています。
そのため、複数のアプリケーションをマウントしているプロジェクトを 0.12.0 に移行する場合は、
デフォルトルートを持つアプリケーションを `config/apps.rb` 内の最後に記載するようにした方が無難です。

ちなみに、上記の例で `/foo/other` にアクセスした場合、
結果としては`this is app.`を返しますが、App2 の not_found ハンドラ−は発動します。
開発環境でのログ出力はこんな感じ:

```
 DEBUG -       GET (0.0118s) /foo/other - 404 Not Found
 DEBUG -       GET (0.0022s) /foo/other - 200 OK
```

なおこの変更に伴い、0.12.0 への移行時には `config/apps.rb` の設定を変更し、
DirectoryTraversal の保護を無効にする必要があります。

```ruby:config/apps.rb
# before
set :protection, true
# after
set :protection, except: :path_traversal
```

## Task Generator の追加

Rake タスクを生成するためのジェネレータが追加されました。
以下のコマンドを実行すると:

```
$ padrino g task seed -n db -d "Populates\ the\ database"
```
`tasks/db_seed.rake`というファイルが作成され、`db`という名前空間の`seed`というタスクが定義されます。

```ruby:tasks/db_seed.rake
namespace :db do
  desc "Populates the database"
  task :seed => :environment do
    # This is a custom task.
  end
end
```

## アプリケーション間でのテンプレートの共有が可能に?

別のアプリケーション配下にある view のパスを返す `Padrino::Application#view_path` メソッドと、別のアプリケーション配下にある layout のパスを返す `Padrino::Application#layout_path` メソッドが追加されました。

```ruby
Sample::App.view_path("users/index")
# => "/path/to/sample/app/views/users/index"

Sample::App.layout_path("application")
# => "/path/to/sample/app/views/layouts/application"
```

ただ、現状ではこれで取得したパスを render や partial に渡しても、ちゃんと解釈してくれません。
次バージョンでの修正を待ちましょう。

## CSRF 保護対象のフィルタリング

protect_from_csrf をセットする際に、:except オプションで保護対象から除くパスを指定できるようになりました。

```ruby:app/app.rb
module Sample
  class App < Padrino::Application
    #...
    set :protect_from_csrf, except: %r{/__better_errors/\d+/\w+\z}
```

上記では better_errors が表示するページを対象外にするよう、正規表現で指定しています。

正規表現以外に Proc オブジェクトを渡すことで、env を使った柔軟な条件指定も可能になっています。

```ruby:app.rb
module Sample
  class App < Padrino::Application
    #...
    DISALLOWED_CSRF_PATHS = ["/foo", "/bar"]
    set :protect_from_csrf, except: ->(env){ DISALLOWED_CSRF_PATHS.include?(env['PATH_INFO']) }
```

## JS, CSS ファイルの格納先ディレクトリが指定可能に

JavaScript と CSS のファイル格納先として、
デフォルトではそれぞれ `public/stylesheets` と `public/javascripts` が使われます。
以下の設定を行うことでそれを変更できるようになりました。

```ruby:app.rb
module Sample
  class App < Padrino::Application
    set :css_asset_folder, 'css'
    set :js_asset_folder, 'js'
  end
end
```

上記の設定で、`stylesheet_link_tag` と `javascript_include_tag` は、
それぞれ `public/css` と `public/js` にファイルがあることを期待するようになります。

## 他にもいろいろ

改善やバグ修正が行われていますので、[公式ブログ](http://www.padrinorb.com/blog/padrino-0-12-0-activesupport-4-rewritten-reloader-smarter-rendering-and-loads-more)か[CHANGES](http://www.padrinorb.com/changes)をチェックしてみてください。