railsで相互限定公開の実装

<h1>はじめに</h1>
相互フォロワー限定で記事を投稿する機能を追加しようと思ったのですが、私の調べ方が足りなかったのかなかなか似たような機能の記事が見当たらず時間がかかったので記録します。
初心者故拙いところも多々ありますので何か間違っているところがあればご指摘いただけると嬉しいです。

<h1>前提</h1>
<b>・フォロー機能の実装</b>
<a href="https://qiita.com/bindingpry/items/e15f38fb2ca298012684">こちら</a>の記事を参考にさせていただきました。
:warning:フォロー機能には<a href="https://github.com/tcocca/acts_as_follower">acts_as_follower</a>というgemを必ず使用してください。
後述のfollowed_by?メソッドはこのgemによって定義されていますので、その他のフォロー機能の記事を参考にした方は<a href="https://github.com/tcocca/acts_as_follower">acts_as_follower</a>のfollowed_by?部分がどう定義しているか確認して各々で定義してあげてください
(※私はそれが結局わからず別のフォロー機能記事を参考にしていましたが、こちらのgemに乗り換えました。)

<b>・マイページ機能の実装</b>

<b>・公開非公開機能の実装</b>
<a href="https://qiita.com/manacat1999/items/3e335542935c47c640e7">こちら</a>の記事を参考にさせていただきました。
当記事では公開設定をプルダウンを利用して進めていきます。

<b>・投稿機能の実装</b>

当記事ではpostモデルを使用しております。モデル名は各自で変更してください。

<h1>実装</h1>
<b>・投稿画面</b>

```posts/new.html.erb
<%= f.select :privacy, [["公開", 1], ["非公開", 2], ["相互限定", 3]] %>
```
プルダウン部分に「相互限定」の公開範囲を追加します。
編集機能がある人はそこにも同じように追加します。

<b>・タイムライン</b>
![_likes.html.erb - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527148/3629073b-e5f8-8ca4-3088-5fee98dbb8d8.png)
今回はタブ機能を用いて
・投稿一覧
・フォローしているユーザーと自分の投稿一覧
を分けて表示できるように実装していきます。

タブ機能は<a href="https://web.monogusa-note.com/flexible-tabs-only-css#toc1">こちら</a>の記事の「ボタンが幅に合わせて伸縮するデザイン」を使用させていただきました。

```posts/index.html.erb
<% if user_signed_in? %>
    <div class="tab-wrap">
        <input id="TAB-01" type="radio" name="TAB" class="tab-switch" checked="checked" /><label class="tab-label" for="TAB-01">Posts all</label>
        <div class="tab-content">
            <% @posts.each do |t| %>
                <% if t.privacy=="1" %>
                    投稿
                <% end %>
            <% end %>
        </div>
        <input id="TAB-02" type="radio" name="TAB" class="tab-switch" /><label class="tab-label" for="TAB-02">Follow</label>
        <div class="tab-content">
            <% @posts.each do |t| %>
                <% if (t.user.followed_by? current_user) || current_user == t.user %>
                    <% if t.privacy=="3"&&(current_user.followed_by? t.user) && (t.user.followed_by? current_user) || t.privacy=="1" %>
                        投稿
                    <% end %>
                <% end %>
            <% end %>
        </div>
    </div>
<% else %>
    <% @posts.each do |t| %>
        <% if t.privacy=="1" %>
            投稿
        <% end %>
    <% end %>
<% end %>
```
※投稿部分は各自で表示させたいものを入れてください

<b>解説</b>
if文ではユーザーのログイン状態によって分岐しています。
・ユーザーがログインしているとき、Tab1ではすべての公開記事を表示、Tab2ではフォローしているユーザーと自分の投稿のみを表示
(相互フォローしているユーザーがいる場合は限定公開の記事も表示する)
・ユーザーがログインしていないとき、すべての公開記事を表示

```<% if (t.user.followed_by? current_user) || current_user == t.user %>```
この部分でcurent_userがフォローしている投稿、またはcurrent_userの投稿を表示するように指示しています。



<b>・マイページ</b>

```users/show.html.erb
<% if current_user.id == @user.id %>
    <div class="tab-wrap">
            <input id="TAB-01" type="radio" name="TAB" class="tab-switch" checked="checked" /><label class="tab-label" for="TAB-01">Release</label>
            <div class="tab-content">
                <% @user.posts.each do |t| %>
                    <% if t.privacy=="1" %>
                        投稿
                    <% end %>
                <% end %>
            </div>
            <input id="TAB-02" type="radio" name="TAB" class="tab-switch" /><label class="tab-label" for="TAB-02">Follow</label>
            <div class="tab-content">
                <% @user.posts.each do |t| %>
                    <% if t.privacy=="3"&&t.user.id==current_user.id %>
                        投稿
                    <% end %>
                <% end %>
            </div>
            <input id="TAB-03" type="radio" name="TAB" class="tab-switch" /><label class="tab-label" for="TAB-03">Private</label>
            <div class="tab-content">
                <% @user.posts.each do |t| %>
                    <% if t.privacy=="2"&&t.user.id==current_user.id %>
                        投稿
                    <% end %>
                <% end %>
            </div>
    </div>
<% elsif (current_user.followed_by? @user) && (@user.followed_by? current_user) %>
    <div class="tab-wrap">
        <input id="TAB-01" type="radio" name="TAB" class="tab-switch" checked="checked" /><label class="tab-label" for="TAB-01">Release</label>
        <div class="tab-content">
            <% @user.posts.each do |t| %>
                <% if t.privacy=="1" %>
                    投稿
                <% end %>
            <% end %>
        </div>
        <input id="TAB-02" type="radio" name="TAB" class="tab-switch" /><label class="tab-label" for="TAB-02">Follow</label>
        <div class="tab-content">
            <% @user.posts.each do |t| %>
                <% if t.privacy=="3" %>
                    投稿
                <% end %>
            <% end %>
        </div>
        <input id="TAB-03" type="radio" name="TAB" class="tab-switch" /><label class="tab-label" for="TAB-03">Likes</label>
        <div class="tab-content">
            <% @user.liked_posts.each do |t| %>
                <% if t.privacy=="1" || t.privacy=="3"&& (current_user.followed_by? @user) && (@user.followed_by? current_user) %>
                    投稿
                <% end %>
            <% end %>
        </div>
    </div>
<% else %>
    <div class="tab-wrap">
        <input id="TAB-01" type="radio" name="TAB" class="tab-switch" checked="checked" /><label class="tab-label" for="TAB-01">Release</label>
        <div class="tab-content">
            <% @user.posts.each do |t| %>
                <% if t.privacy=="1" %>
                    投稿
                <% end %>
            <% end %>
        </div>
        <input id="TAB-02" type="radio" name="TAB" class="tab-switch" /><label class="tab-label" for="TAB-02">Likes</label>
        <div class="tab-content">
            <% @user.liked_posts.each do |t| %>
                <% if t.privacy=="1" %>
                    投稿
                <% end %>
            <% end %>
        </div>
    </div>
<% end %>
```
※いいね機能を実装していない場合は適宜該当部分を外してください。

<b>解説</b>
・current_userが表示されているユーザーページ本人であるか
・表示されているユーザーページ本人とcurrent_userが相互フォロー状態か
・それ以外か
で分岐させます。

```<% if t.privacy=="1" || t.privacy=="3"&& (current_user.followed_by? @user) && (@user.followed_by? current_user) %>
```
ここでは、公開範囲が全体公開の記事、もしくは公開範囲が限定公開かつcurrent_userが記事の投稿主と相互フォロー状態であるときを指定します。
そうすることで、いいねしている投稿が限定公開の記事であっても、相互フォローの人以外はユーザーページのいいね一覧から見られなくなります。

<b>完成イメージ</b>
-マイページ画面
![_likes.html.erb - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527148/ac85beeb-16e7-955e-ca8b-9e63212338f1.png)

-相互フォロー状態の他人から見たときのマイページ画面
![_likes.html.erb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527148/de8aa4d8-4210-8771-64fa-5b96926a0e7e.png)

-相互フォロワーではないユーザーからみたページ
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527148/d250cb2a-0316-6613-b47e-895b3a2f2d92.png)

<h1>終わりに</h1>
なかなか似たような機能を探すのに手間取って初心者には実装にかなり時間がかかりましたが、たくさんの記事や助けてくださる方に恵まれてなんとか実装することができました。
私のような完全初心者で似たような機能を実装しようと考えている人のために、そしてなにより未来の自分のためにも備忘録として記録しておきます。

<h1>参考記事</h1>
https://qiita.com/bindingpry/items/e15f38fb2ca298012684

https://qiita.com/manacat1999/items/3e335542935c47c640e7

https://qiita.com/bindingpry/items/6790c91f374acc25bea2

https://web.monogusa-note.com/flexible-tabs-only-css#toc1