🌝

[mapメソッド]🍟追記: whereとの違い/joins

2024/07/10に公開

はじめに

最近mapメソッドを使ったので備忘録として記載して行きます。

mapメソッドとは?

mapメソッドを一言で表すと「各要素へ順に処理を実行してくれるメソッド」
配列の各要素に対してブロックを評価し、その結果を新しい配列として返す。。。。🙉ぁ?
イメージできないので今回やったことを具体例として記録しておきます。

前提

・今回のlike/indexページでは、そのユーザーがいいねした投稿(post)一覧を表示したい!
・アソシエーションは済

likes controller
def index
 @liked_posts = @user.likes.map(&:post)
end

このコードでは、@userが持つlikesという関連モデル(has_manyで関連付けられたモデル)からpostを取得。

mapメソッドは、配列やコレクションの各要素に対してブロックを実行し、その結果を新しい配列として返すことができる。つーまーりー🪿
その情報(今回ならpost情報)を配列にしてくれる。
その新しい配列は 今回は@liked_posts に格納される。
それをビューで使用して、特定の操作(例えば、投稿の画像を表示するなど)を行うことができる。🦆
なるほどーーーーーー!!!!!

補足

じゃあ逆にその投稿をいいねした人を出力したかったら

出力したいviewのコントローラー
@liked_users = @post.likes.map(&:user)

でviewで

<%= @liked_users.each do |liked_user| %>
<%= @liked_users.name %>
<% end %>

とかで出力できるってわけね〜〜〜〜〜〜🌝
やっと理解できて嬉しい〜


7/23 追記

likes controller
def show
  @post = Post.find(params[:post_id])
  @liked_users = @post.likes.map(&:user) 
end
を下記に変更
def show
  @post = Post.find(params[:post_id])
  @liked_users = User.joins(:likes).where(likes: { post_id: @post.id })
end
likes controller
def index
  @user = User.find(params[:id])
  @liked_posts = @user.likes.map(&:post)
end
を下記に変更
def index
  @user = User.find(params[:id])
  @liked_posts = Post.joins(:likes).where(likes: { user_id: @user.id })
end

where メソッド

[特徴]
・データベースに対してSQLクエリを実行し、その結果を返します。
(今回ならpostに紐付いたlikeテーブルに紐付いたuserテーブルのuser.idだけを持ってくる)
・非常に効率的で、大量のデータを扱う際には特に有用です。

mapメソッド

[特徴]
・@post オブジェクトをデータベースから取得。
・@post.likes で関連する Like オブジェクトをすべて取得し、メモリにロード。
・各 Like オブジェクトの user メソッドを呼び出して、それぞれのユーザーを取得
(今回ならpostに紐付いたlikeテーブル[オブジェクト]の情報、またlikeに紐付いたuserの情報を一回全部取得してメモリにロードしてそこから必要なuser_id持ってくる)

結論mapより効率がいいため変更🦉

[mapが有用なケース]
・mapは、コレクションの各要素に対してブロックを評価し、その結果を含む新しい配列を返します。例えば、特定の属性だけを抽出したい場合や、各要素に対して計算を行いたい場合に有用です。
・オブジェクトの特定の属性を配列として取得する場合


joins メソッド

[joinsの基本]
目的: 複数のテーブルを結合し、結合されたデータに基づいてクエリを実行するために使用します。
特に、関連するテーブルの情報を一緒に取得する際に便利。

基本構文
Model.joins(:associationモデル[小文字])
# UserモデルがPostモデルに対して`has_many :posts`と関連付けられているとします。
# ユーザーとそのユーザーが投稿したすべてのポストを取得したい場合
# usersテーブルとpostsテーブルを結合し、特定の条件を満たすポストを取得
User.joins(:posts).where(posts: { title: 'Example' })
複数の結合
# users、posts、そしてcommentsテーブルを結合
User.joins(posts: :comments).where(comments: { approved: true })
条件付きの結合
# 条件を指定して結合
User.joins(:posts).where('posts.created_at > ?', 1.week.ago)

Discussion