概要
プログラミングスクールのメンターをしていて、「記事通りに実装したのにうまく動きません。エラーも出てません」って場合がよくあります。
自分も初心者の頃は愚直に記事通りに実装していたのですが、そこからもう一歩進んで、プログラミングを構造的に理解して実装しよう!という内容です。
そもそものコードの意味や、やってることの意味を理解していきましょう!
前提
RailsでWebアプリケーションを作成しています。
実装している機能は以下の通りです。
各機能の解説はここでは省きます。Googleさんに聞いてください!
- 投稿機能
- 一覧表示機能
- 検索機能
- タグ機能
- ページネーション機能
要するに複数個の機能をつけているって状態ですね!
実際のコード
def index
@posts = params[:tag_id].present? ? Tag.find(prams[:tag_id]).posts : Post.all
@posts = Post.all
@posts = Post.where("body LIKE ?", "%" + params[:search] + "%") if params[:search]
@posts = @posts.page(params[:page]).per(5)
end
このような感じです!
tag_id
を使ってでタグ検索をしようとしています。それでうまく動かないって状態ですね。
viewやroutesなどは解説の本筋からそれるため割愛します。
結果から言うと以下の通りに変更すれば、正常に動作します。
def index
@posts = params[:tag_id].present? ? Tag.find(prams[:tag_id]).posts : Post.all
@posts = @posts.where("body LIKE ?", "%" + params[:search] + "%") if params[:search]
@posts = @posts.page(params[:page]).per(5)
end
bodyを検索するコードについて、記事や教材には以下のような実装になっています。なぜそれをPost
ではなく@posts
に変えなければいけないのでしょうか?
def index
@posts = Post.where("body LIKE ?", "%" + params[:search] + "%") if params[:search]
end
以下解説です。
=は代入だよ。変数は箱だよ。
コードの解説の前に、タイトル回収させてください。
@posts = Post.all
上記のイメージはこんな感じです。
箱が変数で、矢印が=って感じです。
すなわち、@posts
って名前がついた箱の中にPost.all
って中身が入ってるってことですね。
各行の解説
変更前のコードがなぜ動かないのか解説します!最初と最後の行は解説不要ですね。アクションの定義をしています。
def index
@posts = params[:tag_id].present? ? Tag.find(prams[:tag_id]).posts : Post.all
@posts = Post.all
@posts = Post.where("body LIKE ?", "%" + params[:search] + "%") if params[:search]
@posts = @posts.page(params[:page]).per(5)
end
2行目
@posts = params[:tag_id].present? ? Tag.find(prams[:tag_id]).posts : Post.all
ここでは三項演算子を使って@posts
の中身を作成していますね。
三項演算子とは
条件 ? trueの場合 : falseの場合
と記述します。
すなわちこの行は
もしパラメーターの中にtag_idというものがあったら、
タグを検索してそこに紐づく投稿を取得、なかったら、投稿を全て取得し、
@postsというインスタンス変数の中身に入れる
ということです。
これによってタグ検索が実現されます。
3行目
@posts = Post.all
この行では
単純に@posts
の中にPost.all
を代入してますね。
すなわち、@posts
の中身が書きかわっていることです。
イメージはこんな感じです
せっかくタグ検索した結果が上書きされて@posts
に入ってしまいます。
削除しましょう!
4行目
@posts = Post.where("body LIKE ?", "%" + params[:search] + "%") if params[:search]
ここでは後置ifを使って条件を付けていますね
やっていることは
もしパラメータの中にsearchがあったら投稿全てからbodyというカラムの中のを
searchであいまい検索をして、取得した結果を@postsに入れる
これも3行目同様に@posts
を書き換えてしまっています.
ですが、タグ検索したものを文字列で検索することも考えられますなので、以下のように書き換えます
@posts = @posts.where("body LIKE ?", "%" + params[:search] + "%") if params[:search]
こうすることで、@posts
の中身を再利用して、再代入が可能です。
イメージは以下です。
5行目
ここはうまく@posts
を再代入できていますね!
解説は省きます。
以上です!
少し冗長になってしまったかもしれませんが、これで、プログラミングのイメージをうまく持ってくれたら幸いです!