vagrant環境＋Ruby on Railsで簡易ブログソフトを作ってみる　後編

前回に続いて、今回はブログの基本機能であるコメント機能を追加していく。

モデルをジェネレートするため、ターミナルに戻る。
# rails generate model Comment commenter:string body:text article:references

するとdb/migrate/xxxxx_create_comments.rbができている。コマンドでマイグレートする。※xxxxxの部分は日付？的な感じの数字。

# rake db:migrate

では、次にDBにコメントとアーティクルの関係を示す。（記事：コメント＝１：多）
app/models/article.rbを編集する。

```rb:article.rb
class Article < ActiveRecord::Base
  has_many :comments
  validates :title, presence: true,
                    length: { minimum: 5 }
end
```

ルートの設定をする。
config/routes.rbを編集する。

```rb:routes.rb
Blog::Application.routes.draw do
  resources :articles do
    resources :comments
  end
  root 'welcome#index'
end
```
次はコメントのコントローラーを作る。
# rails g controller Comment

showにコメントを作る欄を追加する。
app/views/articles/show.html.erb

```erb:show.html.erb
<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>
 
<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>
 
<h2>Add a comment:</h2>
<%= form_for([@article, @article.comments.build]) do |f| %>
  <p>
    <%= f.label :commenter %><br>
    <%= f.text_field :commenter %>
  </p>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
 
<%= link_to 'Back', articles_path %>
| <%= link_to 'Edit', edit_article_path(@article) %>
```

お次はコメントのコントローラーを編集する。
app/controllers/comments_controller.rb

```ruby:comments_controller.rb
class CommentsController < ApplicationController
  def create
    @article = Article.find(params[:article_id])
    @comment = @article.comments.create(comment_params)
    redirect_to article_path(@article)
  end
 
  private
    def comment_params
      params.require(:comment).permit(:commenter, :body)
    end
end
```

次はコメントの一覧を見られるようにする。
app/views/articles/show.html.erbに追加。

```erb:show.html.erb
<h2>Comments</h2>
<% @article.comments.each do |comment| %>
  <p>
    <strong>Commenter:</strong>
    <%= comment.commenter %>
  </p>
 
  <p>
    <strong>Comment:</strong>
    <%= comment.body %>
  </p>
<% end %>
```

続いて、リファクタリングをしていく。
app/views/comments/_comment.html.erbを作成。

```erb:_comment.html.erb
<p>
  <strong>Commenter:</strong>
  <%= comment.commenter %>
</p>
 
<p>
  <strong>Comment:</strong>
  <%= comment.body %>
</p>
```

そしてapp/views/articles/show.html.erbを編集する。

```erb:show.html.erb 
<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>
 
<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>
 
<h2>Comments</h2>
<%= render @article.comments %>
 
<h2>Add a comment:</h2>
<%= form_for([@article, @article.comments.build]) do |f| %>
  <p>
    <%= f.label :commenter %><br>
    <%= f.text_field :commenter %>
  </p>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
 
<%= link_to 'Edit Article', edit_article_path(@article) %> |
<%= link_to 'Back to Articles', articles_path %>
```

ちょっとすっきりした。レンダーが自動的にコメント数の分だけ繰り返してくれているらしい。
次はapp/views/comments/_form.html.erbを作成する。

```erb:_form.html.erb
<%= form_for([@article, @article.comments.build]) do |f| %>
  <p>
    <%= f.label :commenter %><br>
    <%= f.text_field :commenter %>
  </p>
  <p>
    <%= f.label :body %><br>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
```

続いて、再度app/views/articles/show.html.erbを編集。

```erb:show.html.erb
<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>
 
<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>
 
<h2>Comments</h2>
<%= render @article.comments %>
 
<h2>Add a comment:</h2>
<%= render "comments/form" %>
 
<%= link_to 'Edit Article', edit_article_path(@article) %> |
<%= link_to 'Back to Articles', articles_path %>
```

かなりすっきりした！！
じゃあ、次はコメントの削除機能を追加してく。
app/views/comments/_comment.html.erbを編集し削除リンクを付ける。

```erb:_comment.html.erb
<p>
  <strong>Commenter:</strong>
  <%= comment.commenter %>
</p>
 
<p>
  <strong>Comment:</strong>
  <%= comment.body %>
</p>
 
<p>
  <%= link_to 'Destroy Comment', [comment.article, comment],
               method: :delete,
               data: { confirm: 'Are you sure?' } %>
</p>
```
削除機能をコントローラーにも追加して機能を有効化する。
app/controllers/comments_controller.rbを編集。

```rb:comments_controller.rb
class CommentsController < ApplicationController
  def create
    @article = Article.find(params[:article_id])
    @comment = @article.comments.create(comment_params)
    redirect_to article_path(@article)
  end
 
  def destroy
    @article = Article.find(params[:article_id])
    @comment = @article.comments.find(params[:id])
    @comment.destroy
    redirect_to article_path(@article)
  end
 
  private
    def comment_params
      params.require(:comment).permit(:commenter, :body)
    end
end
```
次は記事を消したときにコメントも削除されるようにする。
app/models/article.rbを編集。

```rb:article.rb
class Article < ActiveRecord::Base
  has_many :comments, dependent: :destroy
  validates :title, presence: true,
                    length: { minimum: 5 }
end
```

次はセキュリティ。誰もがブログやコメントを消したり書いたりできては困るので、、、。
app/controllers/articles_controller.rbを編集。

```rb:articles_controller.rb
class ArticlesController < ApplicationController
 
  http_basic_authenticate_with name: "dhh", password: "secret", except: [:index, :show]
 
  def index
    @articles = Article.all
  end
 
  # snipped for brevity
```
コメントの方は削除のみ制限する。
app/controllers/comments_controller.rbを編集。

```ruby:comments_controller.rb
class CommentsController < ApplicationController
 
  http_basic_authenticate_with name: "dhh", password: "secret", only: :destroy
 
  def create
    @article = Article.find(params[:article_id])
    ...
  end
 
  # snipped for brevity
```

これでできた！
超簡易的ブログの完成！！w
なるべく間違わないようにコピペしてますが、コードが間違ってたら教えてください。