db/migrate/xxx_create_comments.rbの次のコードを変更。
PostとCommentは1対多の関係なので、多側のCommentにpost_idという外部キーのフィールドが必要となる。
UserとCommentは1対多の関係なので、多側のCommentにuser_idという外部キーのフィールドが必要となります。
t.text :message
t.integer :post_id
t.integer :user_id
rails db:migrateを実行。
データベースにテーブルを作成します。
rails db:migrate
app/models/post.rbのPostクラスに次のコード追加。
has_many :comments, :dependent => :destroy
PostとCommentは1対多の関係があり、Postは1側なのでリレーションの定義ではhas_manyを使います。また、postsテーブルのデータを削除した場合に関連するcommentsテーブルの全データを削除するために:dependent=> :destroyを指定しています。
app/views/commentsフォルダ作成。
comments配下にnew.html.erbを作成し、次のコードを追加。
<% content_for :title do %>
コメント作成
<% end %>
<%= render 'layouts/error_message', object: @comment %>
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1>コメント作成</h1>
<form action="<%= post_comments_path(@postId) %>" method="post">
<div class="form-group">
<label for="Message">メッセージ</label>
<textarea class="form-control" name="message" id="Message" rows="5" placeholder="Your Comment"></textarea>
</div>
<button type="submit" class="btn btn-primary">送信</button>
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
</form>
</div>
</div>
$postIdをcreateアクションに渡しています。(CommentとPostのデータを関連づけるために使います(関連付けはcreateアクションで行う))
app/controllers/comments_controller.rbを作成し、次のコードを入力。
class CommentsController < ApplicationController
before_action :logged_in_user
def new
# necessary for validation error message
@comment = Comment.new
@postId = params[:post_id]
end
def create
@comment = Comment.new
@comment.message = params[:message]
@comment.post_id = params[:post_id]
@comment.user_id = current_user.id
if @comment.save
redirect_to post_path(:id => params[:post_id])
else
render 'new'
end
end
end
newアクションでshow.html.erbから受け取った$post_idをnew.html.erbに渡しています。(CommentとPostのデータを関連付けるために使います(関連付けはcreateアクションで行う))
createアクションでは次の箇所で関連付けを行っています。
@comment.post_id = parmas[:post_id]
→CommentとPostのデータが関連付けられます。
@comment.user_id = current_user.id
→CommentとUserのデータが関連付けられます。
config/routes.rbのpost箇所を次のコードのように変更。
CommentsControllerのnewとcreateアクションのルートを定義しています。
resources :posts, only: [:index, :new, :create, ;show, :destroy] do
resources :comments, only: [:new, :create]
end
app/views/posts/show.html.erbの次のコードを変更。
@post.idをnewアクションに渡してします。(CommentとPostのデータを関連付けるために使います(関連付けはcreateアクションで行う))
<a helf="<%= new_post_comment_path(:post_id => @post.id) %>"
class="btn btn-primary btn-space-20 pull-right">コメント</a>
app/views/posts/show.html.erbに次のコードを追加
CommentとUserはリレーションを持っているため、comment.user.imageのような参照ができます。
<hr>
<% @post.comments.each do |comment| %>
<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object img-circle" src="<%= "/images/#{comment.user.image}" %>" width=64 height=64>
</a>
</div>
<div class="media-body">
<h5 class="media-heading"><%= comment.user.name %> <small><%= comment.created_at %></small></h5>
<p><%= comment.message %></p>
</div>
</div>
<% end %>
app/views/layouts/_navbar.htmlerbに次のコードを追加
検索ワードを入れるためのフォームをNavbarに追加します。
<form action="<%= posts_path %>" class="navbar-form navbar-left">
<div class="form-group">
<input type="text" name="word" class="form-control" placeholder="Search Messages">
</div>
<button type="submit" class="btn btn-default">投稿検索</button>
</form>
app/controllers
/posts_controller.rbに次のコードに変更
postsテーブルのmessageフィールドのデータの中で検索ワードが含まれているものが抽出される。
ActiveRecordでLIKE検索
http://stackoverflow.com/questions/25416667/rails-4-prevent-sql-injection-using-like-operator-in-sql-query
def index
if params[:word].present?
@posts = Post.where("message like ?",
"%#(params[:word])%").order(created_at: :desc)
else
@posts = post.all.order(created_at: :desc)
end
end