やりたいこと
すでに画像は各投稿での表示はできているので、
各投稿の画像だけを1つのページで表示したい。
なぜ画像一覧ページを作るのか?
今作ってるのはダイエットアプリで、身体の変化がわかるようにするため。
作業内容
すでに画像はデータベースに保存できてるので、あとはデータベースから取ってきて表示するだけだ。
この「画像一覧」を押したら、current_userが投稿した画像一覧が見れるページに遷移するようにしたい。
新しくビューを作る
「画像一覧ページ」なので「image.html.haml」というファイルをpostsディレクトリ下に配置した。
コントローラーに新しくアクションを作る
posts_controllerにimageアクションを追加した。
ルーティングを設定する
# 画像一覧ページ
get "posts/image" => "posts#image"
posts#imageが動くようにルーティングを設定する。
パスを設定する
$ rails routes
で確認して、以下のようにpathを設定した。
ここまででposts#imageが動くようになった。
posts#imageでcurrent_userが投稿した画像データを取得
mapメソッド?
valueメソッド?
current_userが投稿した画像一覧ページができた
結果的に出来上がったページはこちら。
current_userが投稿した画像が新しい順で表示されてる。
該当コードはこちら
#####コントローラー
def image
@posts = Post.where(user_id: current_user.id)
end
これは単純にログイン中ユーザーの投稿を@posts
というインスタンス変数に入れてビューでここから取得できるようにしてる。
ビュー
.content
.images
- @posts.each do |post|
= image_tag post.image.url, class: "my-images"
ここで画像を表示するのに苦労した。
最初は後述の番外編の@images
から取得して表示しようとしたが、これだと表示できなかった。
- @posts.each do |post|
= image_tag post.image.url, class: "my-images"
ログイン中ユーザーの投稿したpostsたちが配列の形で@posts
に入ってるので、それをeachメソッドで1つ1つ取り出して、
その1つ1つ取り出すのに使うのが変数(ここでいうpost)。
@posts
のにはどんな感じでposts(投稿データ)が入ってるかというと、
[1] pry(#<PostsController>)> @posts
Post Load (0.5ms) SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 28
↳ app/controllers/posts_controller.rb:65
=> [#<Post:0x00007fc263764bc0
id: 217,
food: "サラダ",
calorie: 10.5,
protein: 10.5,
fat: 10.5,
carbo: 10.5,
text: "サラダを食べました。",
created_at: Fri, 21 Aug 2020 06:56:52 UTC +00:00,
updated_at: Fri, 21 Aug 2020 06:56:52 UTC +00:00,
user_id: 28,
start_time: nil,
image: "image6.png",
weight: 70.5>,
#<Post:0x00007fc263764a58
id: 219,
food: "サラダ",
calorie: 10.0,
protein: 10.0,
fat: 10.0,
carbo: 10.0,
text: "サラダ",
created_at: Fri, 21 Aug 2020 10:20:31 UTC +00:00,
updated_at: Fri, 21 Aug 2020 10:20:31 UTC +00:00,
user_id: 28,
start_time: nil,
image: "image6.png",
weight: nil>,
こんな感じだ。
@posts.image
とすることで、このうちのimageカラムを指定できる。
上記のような配列から1つ1つ取り出して、それらのimage: "image6.png"
この部分だけを取り出して、
image_tag で表示できるように.url
を付ければOK。
番外編(おお!!ってなったこと)
def image
@images = Post.where(user_id: current_user.id).select(:image).map{ |image| image[:image]}
end
結構感動したのがこれ。
binding.pryするとどうなるかというと、
[1] pry(#<PostsController>)> Post.where(user_id: current_user.id).select(:image).map{ |image| image[:image]}
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 28 ORDER BY `users`.`id` ASC LIMIT 1
↳ (pry):2
Post Load (0.4ms) SELECT `posts`.`image` FROM `posts` WHERE `posts`.`user_id` = 28
↳ (pry):2
=> ["image6.png", "image6.png", "image5.png", "image4.png"]
こんな感じで、画像データを配列の形で取得している。
def image
@images = Post.where(user_id: current_user.id).select(:image).map{ |image| image[:image]}
end
# Post Postモデルの
# .where(user_id: current_user.id) ログイン中ユーザーの投稿を検索して取得
# .select(:image) imageカラムだけ取得
ここまでは簡単。
てっきりこれで画像データを取得できると思ったらできない。
ここまででbinding.pryするとどうなるかというと、
=> [#<Post:0x00007fc261c86290 id: nil, image: "image6.png">,
#<Post:0x00007fc261c85fe8 id: nil, image: "image6.png">,
#<Post:0x00007fc261c85cc8 id: nil, image: "image5.png">,
#<Post:0x00007fc261c85a20 id: nil, image: "image4.png">]
こんな感じで画像のurl以外の情報も出てきてしまうのだ。
どうすればimage6.png
この部分だけ取り出せるかと試行錯誤した結果、上記のやり方で取得できた。
結果的に使わなかったけれど、こういう形で取得できるんだとわかったので、勉強になった。