Padrino入門 1 「Blog Tutorial」編

PadrinoはRubyベースのシンプルなWAF(Web Application Framework)であるSinatraに、Rails風の機能を追加したものです。

ORMやテンプレートエンジンなどのライブラリを自由に選択してプロジェクトを生成することができ、作成したWebアプリケーションはHerokuにデプロイ可能です。

試しに使ってみたので、備忘録がてらPadrinoの使い方について公式ドキュメントをもとに紹介していきます。

Padrinoについて知る

Padrinoに関する参考ページを紹介しておきます。

Blog Tutorial

「Blog Tutorial」では、ごくシンプルなブログシステムを構築します。記事の投稿、投稿者との紐付け、RSSの生成などを行い、最終的にHerokuにデプロイします。

インストール

Padrinoをgemでインストールします。

> gem install padrino

Project の生成

チュートリアルではORMとしてActiveRecord、テンプレート言語として Haml、テストフレームワークとしてShoulda、JavaScript ライブラリとしてjQueryを利用します。

以下のコマンドでプロジェクトのひな形が生成されます。

> padrino generate project sample_blog -t shoulda -e haml -c sass -s jquery -d activerecord -b
> cd sample_blog

末尾の-bフラグは、bundlerで自動的にすべての依存gemをインストールすることを意味しています。(gemはプロジェクトフォルダではなくシステム側にインストールされます)

generate projecコマンドのオプションについて詳しくは--helpで確認できます。

> padrino generate project --help

生成されるファイルは以下のとおりです。

app/               :
    controllers/   : ルーティングとコントローラ
    helpers/       : ヘルパーメソッドの定義
    stylesheets/   : スタイルシート
    views/         : ビューテンプレート
    views/layouts/ : ビューレイアウト
    app.rb         : アプリケーションコア
config/            :
    apps.rb        : アプリケーションのマウント
    boot.rb        : ブート設定
    database.rb    : データベース接続設定
lib/               :
    sass_init.rb   : SASSの設定
public/            : 画像、スタイルシート、 JavaScript などのスタティックファイル
test/              : モデルやコントローラのテスト
    test.rake      :
    test_config.rb :
tmp/               :
.components        : プロジェクト作成時に指定したコンポーネントの情報
.gitignore         :
config.ru          :
Gemfile            : アプリに必要な gem の依存情報
Gemfile.lock       :

app/app.rb に以下を追加します。

get "/" do
  "Hello World!"
end

get :about, :map => '/about_us' do
  render :haml, "%p This is a sample blog created to demonstrate the power of Padrino!"
end

ローカルサーバを起動し、/と/about_usにアクセスして表示を確認します。

> padrino start

Padrino - Blog Tutorial - Project の生成 Padrino - Blog Tutorial - Project の生成

Admin Dashboard のセットアップ

Padirnoには認証付きの管理画面を自動的に生成する機能があります。以下のコマンドでadminサブアプリケーションを生成します。

> padrino generate admin

管理画面で必要になるgemをインストールします。

> bundle install

以下のコマンドでデータベースを初期化します。

> padrino rake ar:create
    db/sample_blog_development.db が0byteで作成されます(省略可能)
> padrino rake ar:migrate
    dbにデータが書き込まれ、db/schema.rb が作成されます
> padrino rake seed
    dbに db/seeds.rb で定義されたデータを取り込みます
    ログイン用のメールアドレスとパスワードの入力を求められます

ローカルサーバを起動すると、http://localhost:3000/admin で管理画面にアクセスできます。

> padrino start

Padrino - Blog Tutorial - Admin Dashboard のセットアップ Padrino - Blog Tutorial - Admin Dashboard のセットアップ

投稿の作成

投稿を新規作成する機能を実装するため、「post」モデルを作成します。

> padrino generate model post title:string body:text
    models/post.rb とmigrateおよびtestが作成されます

マイグレーションを実行します。

> padrino rake ar:migrate
    dbにpostテーブルが追加され、db/schema.rb が更新されます

次に、投稿処理を行う「posts」コントローラを作成します。

> padrino g controller posts get:index get:show
    app/controllers/posts.rb ほかいくつかのファイルが生成されます

app/controllers/posts.rb に基本的なルーティング(:index と :show)を定義します。:indexは投稿一覧を表示し、:showは単一記事を表示します。

SampleBlog.controllers :posts do
  get :index do
    @posts = Post.all(:order => 'created_at desc')
    render 'posts/index'
  end

  get :show, :with => :id do
    @post = Post.find_by_id(params[:id])
    render 'posts/show'
  end
end

postsコントローラのためのビューを作成します。

app/views/posts/index.haml
    - @title = "Welcome"
    #posts= partial 'posts/post', :collection => @posts
app/views/posts/_post.haml
    .post
      .title= link_to post.title, url_for(:posts, :show, :id => post)
      .date= time_ago_in_words(post.created_at || Time.now) + ' ago'
      .body= simple_format(post.body)
app/views/posts/show.haml
    - @title = @post.title
    #show
      .post
        .title= @post.title
        .date= time_ago_in_words(@post.created_at || Time.now) + ' ago'
        .body= simple_format(@post.body)
    %p= link_to 'View all posts', url_for(:posts, :index)

PadrinoのAdmin機能では、「admin_page」により任意のモデルに対するレコードの作成、編集、削除機能を自動的に追加することができます。

投稿をAdmin機能で管理するために、以下のコマンドを実行します。

> padrino g admin_page post

サーバを再起動し、http://localhost:3000/admin にアクセスすると「Posts」タブが追加されています。「Posts」タブの「New」を選択して新規投稿が可能です。

Padrino - Blog Tutorial - 投稿の作成 1 Padrino - Blog Tutorial - 投稿の作成 1

http://localhost:3000/posts にアクセスすると投稿が表示されます。

Padrino - Blog Tutorial - 投稿の作成 2 Padrino - Blog Tutorial - 投稿の作成 2

投稿にアカウントを関連付ける

Postモデルに Account を紐づけられるよう、新しいマイグレーションを追加します。

> padrino g migration AddAccountToPost account_id:integer
    db/migrate/003_add_account_to_post.rb が作成されます

マイグレーションファイルを、現存する投稿すべてに対してユーザーが紐づくように改修します。db/migrate/003_add_account_to_post.rb のself.upに以下を追加します。

# and assigns a user to all existing posts
first_account = Account.first
Post.all.each { |p| p.update_attribute(:account, first_account) }

models/post.rb にバリデーションを定義します。

class Post < ActiveRecord::Base
  belongs_to :account
  validates_presence_of :title
  validates_presence_of :body
end

マイグレーションを実行します。

> padrino rake ar:migrate

admin/controllers/posts.rb の post :create do に以下を追加します。(「@post = Post.new(params[:post])」行の下に追加)

@post.account = current_account

app/views/posts/show.haml の「.body」行の下に以下を追加します。

.details
  .author Posted by #{@post.account.email}

app/views/posts/_post.haml の「.body」行の下に以下を追加します。

.details
  .author Posted by #{post.account.email}

http://localhost:3000/admin からアカウントを作成して記事を投稿し、記事とアカウントが紐付いて表示されることを確認します。

Padrino - Blog Tutorial - 投稿にアカウントを関連付ける Padrino - Blog Tutorial - 投稿にアカウントを関連付ける

Site Layout

app/views/layouts/application.haml を作成します。

!!! Strict
%html
  %head
    %title= [@title, "Padrino Sample Blog"].compact.join(" | ")
    = stylesheet_link_tag 'reset', 'application'
    = javascript_include_tag 'jquery', 'application'
    = yield_content :include
  %body
    #header
      %h1 Sample Padrino Blog
      %ul.menu
        %li= link_to 'Blog', url_for(:posts, :index)
        %li= link_to 'About', url_for(:about)
    #container
      #main= yield
      #sidebar
        - form_tag url_for(:posts, :index), :method => 'get'  do
          Search for:
          = text_field_tag 'query', :value => params[:query]
          = submit_tag 'Search'
        %p Recent Posts
        %ul.bulleted
          %li Item 1 - Lorem ipsum dolorum itsum estem
          %li Item 2 - Lorem ipsum dolorum itsum estem
          %li Item 3 - Lorem ipsum dolorum itsum estem
        %p Categories
        %ul.bulleted
          %li Item 1 - Lorem ipsum dolorum itsum estem
          %li Item 2 - Lorem ipsum dolorum itsum estem
          %li Item 3 - Lorem ipsum dolorum itsum estem
        %p Latest Comments
        %ul.bulleted
          %li Item 1 - Lorem ipsum dolorum itsum estem
          %li Item 2 - Lorem ipsum dolorum itsum estem
          %li Item 3 - Lorem ipsum dolorum itsum estem
    #footer
      Copyright (c) 2009-2010 Padrino

reset.cssをダウンロードして public/stylesheets/reset.css に、application.sassをダウンロードして app/stylesheets/application.sass に配置します。

http://localhost:3000/posts にアクセスしてレイアウトが適用されたことを確認します。

Padrino - Blog Tutorial - Site Layout Padrino - Blog Tutorial - Site Layout

RSS Feed を生成する

app/controllers/posts.rb の「get :index do」行を以下の内容に変更します。

get :index, :provides => [:html, :rss, :atom] do

app/views/posts/index.haml の「#posts」行の前にRSSへの参照を追加します。

- content_for :include do
  = feed_tag(:rss, url(:posts, :index, :format => :rss),:title => "RSS")
  = feed_tag(:atom, url(:posts, :index, :format => :atom),:title => "ATOM")

app/views/posts/index.atom.builder を作成します。

xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
  xml.title   "Padrino Sample Blog"
  xml.link    "rel" => "self", "href" => url_for(:posts, :index)
  xml.id      url_for(:posts, :index)
  xml.updated @posts.first.updated_at.strftime "%Y-%m-%dT%H:%M:%SZ" if @posts.any?
  xml.author  { xml.name "Padrino Team" }

  @posts.each do |post|
    xml.entry do
      xml.title   post.title
      xml.link    "rel" => "alternate", "href" => url_for(:posts, :show, :id => post)
      xml.id      url_for(:posts, :show, :id => post)
      xml.updated post.updated_at.strftime "%Y-%m-%dT%H:%M:%SZ"
      xml.author  { xml.name post.account.email }
      xml.summary post.body
    end
  end
end

app/views/posts/index.rss.builder を作成します。

xml.instruct!
xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
  xml.channel do
    xml.title "Padrino Blog"
    xml.description "The fantastic padrino sample blog"
    xml.link url_for(:posts, :index)

    for post in @posts
      xml.item do
        xml.title post.title
        xml.description post.body
        xml.pubDate post.created_at.to_s(:rfc822)
        xml.link url_for(:posts, :show, :id => post)
      end
    end
  end
end

http://localhost:3000/posts にアクセスし、head内にRSSとAtomへのリンクが追加され、それぞれ正しく生成されることを確認します。

アプリケーションのデプロイ

Herokuへのデプロイでは以下が前提となります。

  • Git がインストールされていること
  • Heroku account がセットアップされていること
  • Heroku gem がインストールされていること

Windows環境特有の問題として、Gemfile.lockのmingw32に関する記述を削除しておく必要があります。以下の行を削除し、個別のgemでも「-mingw32」となっている箇所を削除して下さい。

PLATFORMS
  x86-mingw32

アプリケーションを Git リポジトリとしてセットします。

> git init
> git add .
> git commit -m "initial commit for app"

Herokuにアップロードします。ただしこのままではまだ動作しません。

> heroku create
> git push heroku master

Herokuで動作させるためにデプロイ環境ではPostgreSQLを使用するよう変更を加えます。まず、pgをGemfileの依存関係として追加します。

# Gemfile
group :production do
 gem 'pg'
end

bundleでgemをインストールします。

> bundle install

config/database.rb を production 環境向けに設定します。

# config/database.rb
postgres = URI.parse(ENV['DATABASE_URL'] || '')

ActiveRecord::Base.configurations[:production] = {
  :adapter  => 'postgresql',
  :encoding => 'utf8',
  :database => postgres.path[1..-1],
  :username => postgres.user,
  :password => postgres.password,
  :host     => postgres.host
}

以下のコマンドでRakefileを作成します。

> padrino rake gen

seed.rbで、実行時にメールアドレスとパスワードをコンソール上から入力せずに済むよう直接指定します。

# db/seeds.rb
email     = "xxx@xxx.xxx"
password  = "xxxx"

再度Herokuにアップロードします。アップロード時に自動的にpgのgemがインストールされます。

> git add .
> git commit -m "Added Postgres support"
> git push heroku master

マイグレーションを実行します。

> heroku rake ar:migrate
> heroku rake seed

デプロイされたアプリケーションを開いて動作を確認します。

> heroku open

おわりに

次回は「Generators」編の予定です。

blog comments powered by Disqus