Railsのチュートリアルをやってみた。

Railsのテストと勉強を兼ねてチュートリアルをやってみる。
環境は、前回から引き続きServersMan@VPS上のRailsです。


リンクはコチラ。
Getting Started with Rails — Ruby on Rails Guides


和訳できるほどの英語力は全然ないので、
自分がやったことをダイジェストで。


3番の項目ぐらいまでやることないので割愛。
3.1 Installing Railsも既にやってあるので省略。

3.2 Creating the Blog Application

$ rails new blog
$ cd blog
$ bundle install
$ rake db:create

bundle install?
よく分からなかったのでググったのだけど、
それでもよく分からなかったので、後でもっと調べる。
gem管理の新標準ツール"Bundler"のTips - 昼メシ物語

4 Hello, Rails!

$ rails server

ブラウザからhttp://***.***.***.***:3000/にアクセス。
チュートリアル通りにhttp://localhost:3000にアクセスして、
「できてないじゃん!」とかやったりしてませんから!

うん、オッケ。

$ rails generate controller home index

app/views/home/index.html.erbを編集。

<%# 削除 %>
<h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>

<%# 追加 %>
<h1>Hello, Rails!</h1>
$ rm public/index.html

config/routes.rbを編集。

# 53行目を編集
# root :to => "welcome#index"
root :to => "home#index"

うん、モーマンタイ。

6 Creating a Resource

$ rails generate scaffold Post name:string title:string content:text
$ rake db:migrate

app/views/home/index.html.erbを編集。

<%# 以下の行を追加 %>
<%= link_to "My Blog", posts_path %>

My Blogのリンクをクリックすると、

うん、チュートリアル通り。

app/models/post.rbを編集。

class Post < ActiveRecord::Base
  # 以下の部分を追加
  validates :name,  :presence => true
  validates :title, :presence => true,
                          :length => { :minimum => 5 }
end
$ rails console
Loading development environment (Rails 3.0.3)
irb(main):001:0> p = Post.new(:content => "A new post")
=> #<Post id: nil, name: nil, title: nil, content: "A new post", created_at: nil, updated_at: nil>
irb(main):002:0> p.save
=> false
irb(main):003:0> p.errors
=> #<OrderedHash {:name=>["can't be blank"], :title=>["is too short (minimum is 5 characters)", "can't be blank"]}>

ここもチュートリアル通り。

ブラウザからアクセスして、
New Postリンク→Create Postボタンをクリックすると、

おぉ、ちゃんと入力チェックできとる。

app/views/layouts/application.html.erbを編集。

<%# 9行目のbodyタグに属性を追加 %>
<body style="background: #EEEEEE;">

おっ、ビミョーに灰色に…?

7 Adding a Second Model

$ rails generate model Comment commenter:string body:text post:references
$ rake db:migrate

app/models/post.rbを編集。

class Post < ActiveRecord::Base
  validates :name,  :presence => true
  validates :title, :presence => true,
                    :length => { :minimum => 5 }
  
  # 以下の行を追加
  has_many :comments
end

config/routes.rbを編集。

# 以下の行を変更
# resources :posts
resources :posts do
  resources :comments
end
$ rails generate controller Comments

app/views/posts/show.html.erbを編集。

<%# Content段落の下に追加 %>
<h2>Add a comment:</h2>
<%= form_for([@post, @post.comments.build]) do |f| %>
  <div class="field">
    <%= f.label :commenter %><br />
    <%= f.text_field :commenter %>
  </div>
  <div class="field">
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
 
<%# 何故かリンクのテキストが変わってるので、合わせておく %>
<%# <%= link_to 'Edit', edit_post_path(@post) %> | %>
<%# <%= link_to 'Back', posts_path %> %>
<%= link_to 'Edit Post', edit_post_path(@post) %> |
<%= link_to 'Back to Posts', posts_path %> |

app/controllers/comments_controller.rbを編集。

class CommentsController < ApplicationController
  # 以下のメソッドを追加
  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.create(params[:comment])
    redirect_to post_path(@post)
  end
end

app/views/posts/show.html.erbを編集。

<%# Content段落の下に追加 %>
<h2>Comments</h2>
<% @post.comments.each do |comment| %>
  <p>
    <b>Commenter:</b>
    <%= comment.commenter %>
  </p>
 
  <p>
    <b>Comment:</b>
    <%= comment.body %>
  </p>
<% end %>

で、ブラウザで見てみる。

おぉ、コメント欄が増えてる。

8 Refactoring

app/views/comments/に、_comment.html.erbを新規作成。
中身は以下の通り。

<p>
  <b>Commenter:</b>
  <%= comment.commenter %>
</p>
 
<p>
  <b>Comment:</b>
  <%= comment.body %>
</p>

app/views/posts/show.html.erbを編集。

<h2>Comments</h2>
<%# さっき追加した以下の内容をごっそり削除 %>
<!--
  <% @post.comments.each do |comment| %>
    <p>
      <b>Commenter:</b>
      <%= comment.commenter %>
    </p>
 
    <p>
      <b>Comment:</b>
      <%= comment.body %>
    </p>
  <% end %>
-->
<%# 以下の内容を追加 %>
<%= render :partial => "comments/comment",
           :collection => @post.comments %>

app/views/comments/に、_form.html.erbを新規作成。
中身は以下の通り。

<%= form_for([@post, @post.comments.build]) do |f| %>
  <div class="field">
    <%= f.label :commenter %><br />
    <%= f.text_field :commenter %>
  </div>
  <div class="field">
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

app/views/posts/show.html.erbを編集。

<h2>Add a comment:</h2>
<%# 以下の部分もごっそり削除 %>
<!--
  <%= form_for([@post, @post.comments.build]) do |f| %>
    <div class="field">
      <%= f.label :commenter %><br />
      <%= f.text_field :commenter %>
    </div>
    <div class="field">
      <%= f.label :body %><br />
      <%= f.text_area :body %>
    </div>
    <div class="actions">
      <%= f.submit %>
    </div>
  <% end %>
-->
<%# 以下の内容を追加 %>
<%= render "comments/form" %>

show.html.erbがスッキリしたー。
そうか、だからリファクタリングっていう章だったのね。

見た目も、機能も変わりなし。

9 Deleting Comments

app/views/comments/_comment.html.erbを編集。

<%# 以下の内容を追加 %>
<p>
  <%= link_to 'Destroy Comment', [comment.post, comment],
               :confirm => 'Are you sure?',
               :method => :delete %>
</p>

app/controllers/comments_controller.rbを編集。

# 以下のメソッドを追加
def destroy
    @post = Post.find(params[:post_id])
    @comment = @post.comments.find(params[:id])
    @comment.destroy
    redirect_to post_path(@post)
end

app/models/post.rbを編集。

# has_many :commentsに:dependent => :destroyを追加
# has_many :comments
has_many :comments, :dependent => :destroy

コメント削除機能、実装完了。

10 Security

app/controllers/application_controller.rbを編集。

# 以下を追加
private
 
def authenticate
  authenticate_or_request_with_http_basic do |user_name, password|
    user_name == 'admin' && password == 'password'
  end
end

app/controllers/posts_controller.rbを編集。

# 2〜3行目あたりに以下を追加
before_filter :authenticate, :except => [:index, :show]

app/controllers/comments_controller.rbを編集。

# やっぱり2〜3行目あたりに以下を追加
before_filter :authenticate, :only => :destroy

おぉ、ベーシック認証。
ただ、ソースに書いてあるにも関わらず、
「IDとパスワード分かんない…orz」と途方にくれてたのはナイショ。

11 Building a Multi-Model Form

$ rails generate model tag name:string post:references
$ rake db:migrate

app/models/post.rbを編集。

# 以下の内容を追加
has_many :tags
 
accepts_nested_attributes_for :tags, :allow_destroy => :true,
  :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
<%# 一行目に追加 %>
<% @post.tags.build %>

<%# 2行目:なぜか変数名が変わってるので一応合わせておく(参照している部分も適宜修正) %>
<%# <%= form_for(@post) do |f| %> %>
<%= form_for(@post) do |post_form| %>

<%# 25〜26行目あたり:content段落の下に追加 %>
  <h2>Tags</h2>
  <%= render :partial => 'tags/form',
             :locals => {:form => post_form} %>

app/views/下にtagsディレクトリを作成。
そのtagsディレクトリ下に、_form.html.erbを作成。
中身は以下の通り。

<%= form.fields_for :tags do |tag_form| %>
  <div class="field">
    <%= tag_form.label :name, 'Tag:' %>
    <%= tag_form.text_field :name %>
  </div>
  <% unless tag_form.object.nil? || tag_form.object.new_record? %>
    <div class="field">
      <%= tag_form.label :_destroy, 'Remove:' %>
      <%= tag_form.check_box :_destroy %>
    </div>
  <% end %>
<% end %>

app/views/posts/show.html.erbを修正。

<%# 17行目あたりのContent段落の下に追加 %>
<p>
  <b>Tags:</b>
  <%= @post.tags.map { |t| t.name }.join(", ") %>
</p>

おぉ、タグ機能、出来ました!

12 View Helpers

app/helpers/posts_helper.rbを編集。

module PostsHelper
  # 以下のメソッドを追加
  def join_tags(post)
    post.tags.map { |t| t.name }.join(", ")
  end
end

app/views/posts/show.html.erbを編集。

<p>
  <b>Tags:</b>
  <%# 20行目あたりのタグ機能を修正 %>
  <%# <%= @post.tags.map { |t| t.name }.join(", ") %> %>
  <%= join_tags(@post) %>
</p>

うん、問題なさそう。

次の章は「13 What’s Next?」なので、
とりあえずこれで終わりかな。

あー、長かった。
お疲れ様でしたー。