インストール
 gem でインストール
  gem install rails
MySQL を使うので
  gem install mysql
 Getting Started with Rails をやってみる。
 アプリケーションの作成。
MySQL を使う。
  rails blog -d mysql
これで blog ディレクトリ以下にいっぱいファイルが作成される。
  rake -T
で、rake のタスクがいっぱい表示された。
 RSpec を使うために
  script/plugin install git://github.com/dchelimsky/rspec.git -r 'refs/tags/1.2.9' script/plugin install git://github.com/dchelimsky/rspec-rails.git -r 'refs/tags/1.2.9' script/generate rspec
 DB を作成する。
次で blog_development MySQL にデータベースが作成される。 RSpec のために test の方も作る。
  rake db:create rake db:create RAILS_ENV=test
 Web サーバの実行
  script/server
http://localhost:3000/ にアクセスして動いていることを確認。
About your application’s environment をクリックすると各バージョンが表示される。
script/about でも表示される。
 RSpec の実行
次でずっと全テストが走るつづける。
  autospec
緑は OK 赤は NG。
apps/blog/spec/spec.opts の —format progress を —format specdoc とすると仕様が表示されるようになる。
次で一回だけ全テストが走る。
  rake spec
 最初のページを作る
home コントローラを作る。inedx アクション付きで。 RSpec のために rspec_controller で。
  script/generate rspec_controller home index
app/views/home/index.html.erb を次の内容に編集する。
 <h1>Hello, Rails!</h1>
<p>まみむめも♪</p>
http://localhost:3000/home/index にアクセスすると上記内容が表示される。
このページを http://localhost:3000/ で表示するには public/index.html を削除し、config/routes.rb で map.root を指定する。
   map.root :controller => "home"
 scaffold を使ってみる
モデル、ビュー、コントロールが一気にできちゃう。これも rspec_scaffold で。
  script/generate rspec_scaffold Post name:string title:string content:text rake db:migrate rake db:migrate RAILS_ENV=test
M-x rinari-sql してできたテーブルを確認してみる。
 mysql> show tables;
+----------------------------+
| Tables_in_blog_development |
+----------------------------+
| posts                      |
| schema_migrations          |
+----------------------------+
2 rows in set (0.00 sec)
mysql> SHOW FIELDS FROM `posts`;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | YES  |     | NULL    |                |
| title      | varchar(255) | YES  |     | NULL    |                |
| content    | text         | YES  |     | NULL    |                |
| created_at | datetime     | YES  |     | NULL    |                |
| updated_at | datetime     | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
id, created_at, updated_at はデフォルトで存在するらしい。
app/views/home/index.html.erb にポストページへのリンクを追加する。
 <h1>Hello, Rails!</h1>
<p>まみむめも♪</p>
<%= link_to "ブログへ", posts_path %>
posts_path は config/routes.rb に次の行が script/generate scaffold によって追加されて使えるようになっている。レストフルなフレーバー?
  map.resources :posts
追加したリンクをクリックすると posts の CRUD ができるようになっている。
autospec が赤になっているので、テストのためのテスト的に spec/views/home/index.html.erb_spec.rb を修正する。 11行目。「まみむめも♪」と書かれた p タグがあることを期待している。
     response.should have_tag('p', %r[まみむめも♪])
 validation を追加する
Post に次の validation を追加する。
  - name は必須
- title は必須
- title は5文字以上
app/models/post.rb をいじる。
 class Post < ActiveRecord::Base
  validates_presence_of :name, :title
  validates_length_of :title, :minimum => 5
end
RSpec も。
 # -*- coding: utf-8 -*-
require 'spec_helper'
describe Post do
  before(:each) do
    @valid_attributes = {
      :name => "value for name",
      :title => "value for title",
      :content => "value for content"
    }
  end
  it "should create a new instance given valid attributes" do
    Post.create!(@valid_attributes)
  end
  it "name がないと不正" do
    post = Post.create(@valid_attributes)
    post.name = nil
    post.save
    post.should_not be_valid
  end
  it "title がないと不正" do
    post = Post.create(@valid_attributes)
    post.title = nil
    post.save
    post.should_not be_valid
  end
  it "title が4文字だと不正" do
    post = Post.create(@valid_attributes)
    post.title = "あいうえ"
    post.save
    post.should_not be_valid
  end
  it "title が5文字だと正常" do
    post = Post.create(@valid_attributes)
    post.title = "あいうえお"
    post.save
    post.should be_valid
  end
  it "title が6文字でも正常" do
    post = Post.create(@valid_attributes)
    post.title = "あいうえおか"
    post.save
    post.should be_valid
  end
end
 パーシャルテンプレート
app/views/posts/new.html.erb と app/views/posts/edit.html.erb の共通部分をパーシャルテンプレートにする。
共通部分を選択して M-x rinari-extract-partial とすると、名前をきいてくるので form と入力する。 _form.html.erb が作成され、new.html.erb と edit.html.erb は次のようにに編集する。
 <%= render :partial => 'form' %>
 コメントできるようにする
ポストに対してコメントできるようにする。 rspec_model で Comment モデルを作成。
 script/generate rspec_model Comment commenter:string body:text post:references
rake db:migrate
rake db:migrate RAILS_ENV=test
Post は Comment をいくつか持っている。has_many で指定。
 class Post < ActiveRecord::Base
  validates_presence_of :name, :title
  validates_length_of :title, :minimum => 5
  has_many :comments
end
config/routes.rb でネスト。
 map.resources :posts, :has_many => :comments
rspec_controller で Comment のコントローラを作る。ビューのあるアクションのみ引数に指定する。
  script/generate rspec_controller Comments index show new edit
できた app/controllers/CommentsController の中身を実装する。
view を編集(コピペ)。
app/views/posts/show.html.erb にコメントへのリンクを追加。
 <%= link_to 'Back', post_comments_path(@post) %>
 Building a Multi-Model Form
複数のモデルを扱うフォーム。タグを付けられるようにする。
 script/generate rspec_model tag name:string post:references
rake db:migrate
rake db:migrate RAILS_ENV=test
Post モデルを修正。
 # -*- coding: utf-8 -*-
class Post < ActiveRecord::Base
  validates_presence_of :name, :title
  validates_length_of :title, :minimum => 5
  has_many :comments
  has_many :tags
  accepts_nested_attributes_for(:tags,
                                # 削除チェックボックスのために
                                :allow_destroy => :true,
                                :reject_if => proc { |attrs|
                                  # すべての属性が必須
                                  attrs.all? { |k, v|
                                    v.blank?
                                  }
                                })
end
apps/blog/app/views/posts/_form.html.erb を修正。 new のときのために1行目に ... build if ... を追加。 <% post_form.fields_for :tags do |tag_form| %> を追加。
 <% @post.tags.build if @post.tags.empty? %>
<% form_for(@post) do |post_form| %>
  <%= post_form.error_messages %>
  <p>
    <%= post_form.label :name %><br />
    <%= post_form.text_field :name %>
  </p>
  <p>
    <%= post_form.label :title %><br />
    <%= post_form.text_field :title %>
  </p>
  <p>
    <%= post_form.label :content %><br />
    <%= post_form.text_area :content %>
  </p>
  <h2>タグ</h2>
  <% post_form.fields_for :tags do |tag_form| %>
    <p>
      <%= tag_form.label :name, 'タグ:' %>
      <%= tag_form.text_field :name %>
    </p>
    <% unless tag_form.object.nil? || tag_form.object.new_record? %>
      <p>
        <%= tag_form.label :_delete %>
        <%= tag_form.check_box :_delete %>
      </p>
    <% end %>
  <% end %>
  <p>
    <%= post_form.submit '保存' %>
  </p>
<% end %>
 テスト
 RSpec でのテスト
 ビューのテスト
mock_model でモデルを作って assigns でビューから見えるようにする、ということだろうか。
spec/views/comments/index.html.erb_spec.rb
 # -*- coding: utf-8 -*-
require 'spec_helper'
describe "/comments/index" do
  before(:each) do
    @comment = mock_model(Comment,
                          :commenter => '田中京子',
                          :body => '寒かったですね。')
    @post = mock_model(Post,
                       :name => '山田太郎',
                       :title => '今日のできごと',
                       :content => '今日はくもりでした。')
    assigns[:post] = @post
    assigns[:comments] = [@comment]
    render 'comments/index'
  end
  #Delete this example and add some real ones or delete this file
  it "should tell you where to find the file" do
    response.should have_tag('td', @comment.commenter)
    response.should have_tag('td', @comment.body)
  end
end
spec/views/comments/show.html.erb_spec.rb
 # -*- coding: utf-8 -*-
require 'spec_helper'
describe "/comments/show" do
  before(:each) do
    @comment = mock_model(Comment,
                          :commenter => '田中京子',
                          :body => '寒かったですね。')
    @post = mock_model(Post,
                       :name => '山田太郎',
                       :title => '今日のできごと',
                       :content => '今日はくもりでした。',
                       :comments => [@comment])
    assigns[:post] = @post
    assigns[:comment] = @comment
    render 'comments/show'
  end
  #Delete this example and add some real ones or delete this file
  it "should tell you where to find the file" do
    response.should have_tag('p', "#{@comment.commenter} さんのコメント")
    response.should have_tag('p', @comment.body)
  end
end
spec/views/comments/edit.html.erb_spec.rb
 # -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
require 'spec_helper'
describe "/comments/edit" do
  before(:each) do
    @comment = mock_model(Comment,
                          :commenter => '田中京子',
                          :body => '寒かったですね。')
    @post = mock_model(Post,
                       :comments => [@comment])
    assigns[:post] = @post
    assigns[:comment] = @comment
    render 'comments/edit'
  end
  #Delete this example and add some real ones or delete this file
  it "should tell you where to find the file" do
    response.should have_tag('input[id=comment_commenter][value=?]',
                             @comment.commenter)
    response.should have_tag('textarea[id=comment_body]',
                             @comment.body)
  end
end
 モデルのテスト
自動的に作られた comments_controller_spec.rb のテストが失敗するので、 before(:each) でモックを仕込む。
   before(:each) do
    @mock_comment = mock_model(Comment, :name => '田中京子',
                               :body => 'あ')
    @mock_post = mock_model(Post,
                            :name => '山田太郎',
                            :comments => [@mock_comment])
    @mock_post.comments.stub!(:build).and_return(Comment.new)
    Post.stub!(:find).and_return(@mock_post)
  end