0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rails map,flatten,pluckなどなど…

Last updated at Posted at 2023-07-05

はじめに

  • 調べたり試行錯誤したりして実装したメソッドについて、自身の定着のためにまとめました
  • 学習内容の備忘録です

目次

  1. コミュニティIDの取得について(コードの【A】参照)
  2. UserモデルとCommunityモデルのJoin操作について(コードの【B】参照)
  3. コミュニティに所属するユーザーの投稿を取得することについて(コードの【C】参照)

以下の記述について、自分なりに苦労したため、まとめてみます。

post.html.erb
#省略

def index
    @post = Post.new
    if current_user.communities.present?

      #【A】
      community_ids = current_user.communities
                                  .map(&:subtree_ids)
                                  .flatten

      #【B】
      community_user_ids = User.joins(:communities)
                               .where(communities: { id: community_ids })
                               .pluck(:id)

      #【C】
      @posts = Post.includes(:user)
                   .where(users: { is_deleted: false, id: community_user_ids })
                   .order(created_at: :desc)
                   .page(params[:page]).per(9)
    else
      
      #省略

    end
  end

#省略

1.コミュニティIDの取得について

【A】

community_ids = current_user.communities
                            .map(&:subtree_ids)
                            .flatten

①map(&:subtree_ids)は、current_user.communitiesの各コミュニティに対してsubtree_idsメソッドを呼び出し、子孫コミュニティのIDの配列を取得

.map(&:subtree_ids)

補足
mapメソッドは、配列の各要素に対して指定されたブロックまたはメソッドを実行し、結果の配列を返す

補足2
subtree_idsとは、「gem ancestry」のインスタンスメソッドで、返り値は、「自分のレコードと子レコード以下全てのレコードのidを取得」する。

②flattenメソッドは、多次元配列をフラットな一次元配列に変換

.flatten

2.UserモデルとCommunityモデルのJoin操作について

【B】

community_user_ids = User.joins(:communities)
                         .where(communities: { id: community_ids })
                         .pluck(:id)

①joins(:communities)は、UserモデルとCommunityモデルを関連付けて結合

User.joins(:communities)

②where(communities: { id: community_ids })は、結合したデータの中から指定されたコミュニティIDに該当するものを探してくる

.where(communities: { id: community_ids })

③pluck(:id)は、結果の中からユーザーIDの配列を取得

.pluck(:id)

3.コミュニティに所属するユーザーの投稿を取得することについて

【C】

@posts = Post.includes(:user)
             .where(users: { is_deleted: false, id: community_user_ids })
             .order(created_at: :desc)
             .page(params[:page]).per(9)

①includes(:user)は、関連するユーザーレコードを事前に読み込んでN+1問題を回避

Post.includes(:user)

補足
N+1問題とは、必要なデータを取得するために必要以上のクエリを実行することで、効率性が低下する問題のこと。ここでは、Post.includes(:user)により、投稿と関連するユーザーのデータが一度のクエリで取得できている。

②where(users: { is_deleted: false, id: community_user_ids })は、ユーザーが削除されておらず、かつ指定されたユーザーIDに該当する投稿を選択

.where(users: { is_deleted: false, id: community_user_ids })

③order(created_at: :desc)は、作成日時の降順で結果を並び替え

.order(created_at: :desc)

④page(params[:page]).per(9)は、ページネーションを適用し、指定されたページの投稿を9つずつ取得

.page(params[:page]).per(9)

まとめ

  • メモを見ながら何とか言語化できました
  • 「説明してよ」と言われて、何も見ずに説明できるように、さらに理解を深めていきます

⚠️学習4ヶ月目の初学者による投稿です。
⚠️間違いがあるかもしれません。ご容赦ください。
⚠️ご指導、ご教授いただけると幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?