railsアプリのユーザー詳細画面に、SNSリンクをアイコンとして表示する方法



#前提
```Rails 6.0.3.1```
```ruby 2.6.3```


どーも！@vinakaです！　お疲れ様です。
現在
railsでオリジナルアプリの製作中です。
ユーザーの詳細画面に、各種SNSのリンクを追加したいなと思い実装してみました。
**今回は「```twitter,facebook,instagram```のアイコンを押すと、登録したURLに飛ぶ」ことを目標にしたいと思います。**

**わりとありそうで、ネットに情報が少なかったのでまとめてみました。**
実装自体は、簡単で初実装でも1~2時間で終わると思います。

記事自体は、```下準備パート```と```実装パート```に分かれています。
少し長いですが、お付き合いいただけますと幸いです。

***

#下準備

##①Userモデルにカラムを追加する


Userモデルに、追加したいSNSのリンクを、**文字列**で追加します。
今回自分の場合は、```twiiter、facebook、instagram```のリンクを追加したかったので、Userモデルに```twiiter、facebook、instagram```カラムを追加しました。


```:ターミナル
rails generate migration AddSnslinkToTitles twitter:string facebook:string instagram:string
```

生成されたmigrationファイルで、カラムが追加されているかどうか確認。

```/db/migrate/20200606151806_add_sns_to_users.rb
class AddSnsToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :twitter, :string
    add_column :users, :facebook, :string
    add_column :users, :instagram, :string
  end
end
```
問題なければ、```rails db:migrate```しデータベースに変更を反映します。

```ターミナル:ターミナル
rails db:migrate
```

下準備として、カラムの追加は完了です。

##②ストロングパラメーターにカラムを追加する

**僕自身は、ここでハマりました。**
エラーは起きていないけれど、データベースに保存ができていない状態でした。
ストロングパラメーターを設定している場合が、忘れずに```twiiter、facebook、instagram```カラムを追加しましょう。

```ruby:app/controllers/users_controller.rb

 private
      def user_params
        params.require(:user).permit(:name, :email, :nationality, :password, :password_confirmation, :image, :twitter, :facebook, :instagram)
      end
```

いろいろごちゃごちゃ書いてありますが、**大事なのは```permit```内の最後の三つです。**

##③rails6にFont Awesomeを導入

各SNSの```アイコン```を押すと、自身がURL指定したアカウントに飛ばすような仕様にしたいので、
**アイコンが必要になります。**

今回は、Font Awesomeを使って実現していきます。

以下記事のとおり、Font Awesomeを導入しました。
[Rails 6 に Fort Awesome 5 を導入する](https://qiita.com/SaitoJP/items/bda11d7bd4e8ad35331a)

###パッケージのインストール

```:ターミナル
yarn add @fortawesome/fontawesome-free
```

```yarn addコマンド```について
[yarn add](https://classic.yarnpkg.com/ja/docs/cli/add/)



###application.js にインポート

```ruby:app/javascript/packs/application.js
import '@fortawesome/fontawesome-free/js/all'
```

rails6ではapplication.jsの配置されている位置が変わりました。
assetsの中では、なくなりましたね。

以下記事Rails６について、詳しくわかりやすくまとめていて参考になりました。
[Ruby on Rails 6の主要な新機能・機能追加・変更点](https://qiita.com/ryohashimoto/items/622c3bcfb3336cb9317e)

###上記で、アイコンが表示されない場合

もし上記の手順で、アイコンがブラウザで表示されなかったりする場合は、```'font-awesome-sass'```をGemfileに追加し、```bundle i```してみてください。

```ruby:Gemfile
gem 'font-awesome-sass'
```

```:ターミナル
bundle i
```


##④使用したいアイコンを探す

###公式サイト
以下が、Font Awesomeの公式ページになります。
[ Font Awesome 6](https://fontawesome.com/icons?d=gallery)

###SNSアイコンまとめサイト
上記から、一つ一つアイコンを探してもいいのですが、
**SNSアイコンをまとめてくれているサイトをみつけたので、こちらの方が手間が省けると思います。**
[【Font Awesome】アイコンフォントの色・大きさを変える方法
](https://azusas.com/font-awesome-change-colors-sizes/)
ページをスクロールしていくと、ちょうど真ん中あたりに、
**【Font Awesome】アイコンの色を変える方法**
があるので、ご参照ください。
**今回は、使用予定の```twitter,facebook,instagram```をピックアップしましたが、```youtube```や```LINE```もアイコンが存在するので、気になる方は上記のリンクを覗いてみてください。**

```ruby:SNSアイコン

<p><i class="fab fa-twitter"></i></p>
<p><i class="fab fa-facebook-square"></i></p>
<p><i class="fab fa-instagram"></i></p>

```

カラーがデフォルトでは、異なるので公式アイコンに近づけるために
**CSSでカラーを指定します。**

```css:アイコンの装飾
/*Twitter*/
.fa-twitter{color:#1da1f2;}
/*Facebook*/
.fa-facebook-square{color:#3b5998;}
/*instagram*/
.fa-instagram{color:#e1306c;}
```


使用したいアイコンとその色を指定するCSSまでわかったので、ついに実装パートに入ります。


#実装パート
##❶フォームを作成し、SNSリンクのURLをデータベースに保存する

フォーム内で、表示したいSNSリンクのURLを受け取り、保存します。
自身はユーザー編集画面にSNSフォームを作りました。
以下は```form＿with```で作成したフォームの内容の一部です。
**SNSリンクは、表示したい人のみの任意項目にしました。**
**そのため、```twitter,facebook,instagramカラム```には```presence```のバリデーションをかけていません。**


```ruby:app/views/users/edit.html.erb
          <%= form_with(model: @user, local: true) do |form| %>

          　 # <% 基本情報(ユーザー名やメールアドレス)の更新は長いので、割愛 %>
　 
            <div class = "sns-link">
              <h2> SNS URL </h2>
              <h4>(Optional)</h4>
              <div class="form-group">
                <%= form.label :twitter, 'Twitter URL', class: 'form-control' %>
                <%= form.text_field :twitter, placeholder: "Optional", class: "form-control" %>
              </div>
              <div class="form-group">
                <%= form.label :facebook, 'Facebook URL', class: 'form-control' %>
                <%= form.text_field :facebook, placeholder: "Optional", class: "form-control" %>
              </div>
              <div class="form-group">
                <%= form.label :instagram, 'Instagram URL', class: 'form-control' %>
                <%= form.text_field :instagram, placeholder: "Optional", class: "form-control" %>
              </div>
              <%= form.submit 'Update', class:'btn-block btn-primary btn-lg ' %>
            </div>
         <% end %>
```

##❷ユーザー詳細画面で表示する

フォームで受け取り、データベースに保存された各SNSのURLをアイコンにして表示していきます。
仕様としては、
**①フォームで受け取ったSNSのリンクがあれば、表示（なければ非表示）
②SNSリンクを受け取った物だけ、アイコンを表示する（フォームでtwiiterのURLのみ受け取ったら、twiitterのアイコンのみ表示して、facebookとinstagramのアイコンは非表示）**

それでは、ユーザー詳細ページに実装していきます。

```ruby:app/views/users/show.html.erb
        <div class = "sns-link">
          <ul class="profile-links">
          #<% ポイント %>
            <% if @user.twitter.present? %>
              <li class="profile-link">
                <%= link_to @user.twitter, target: :_blank do %>
                  <i class="fab fa-twitter-square"></i>
                <% end %>
              </li>
            <% end %>
          #<% ポイント %>
            <% if @user.facebook.present? %>
              <li class="profile-link">
                <%= link_to @user.facebook, target: :_blank do %>
                  <i class="fab fa-facebook-square"></i>
                <% end %>
              </li>
            <% end %>
          #<% ポイント %>
            <% if @user.instagram.present? %>
              <li class="profile-link">
                <%= link_to @user.instagram, target: :_blank do %>
                  <i class="fab fa-instagram"></i>
                <% end %>
              </li>
            <% end %>
            </ul>
        </div>
```

**コメントでポイントと書かれたところで、値が存在するか確認しています。
つまり、データベースに値（URL）が存在する場合は、下記の処理を行います。**

```ruby

<li class="profile-link">
    <%= link_to @user.instagram, target: :_blank do %>
        <i class="fab fa-instagram"></i>
    <% end %>
</li>
```

ちなみに```target: :_blank```はリンクを新しいウィンドウで開くための指定です。



**上記で、データベースに値（URL）が存在するSNSについては、アイコンが表示され、クリックするとURL先に飛ぶことが出来るようになりました**


##❸CSSでレイアウトを整える

あとは、細かいレイアウトなどCSSで指定して終わりです。
自身は、```custom.scss```を作って記述しました。
それとscssを使っているので、```profile-links```の中に、```profile-link```をネストしてしています。

ぶっちゃけ、各アイコンの色の指定以外は、各々の好みやモックアップに合わせてCSSを書いていくと思いますが、```list-style: none;```と``` display: inline-block;```はアイコンを並べる際に使えると思います。

```css:app/assets/stylesheets/custom.scss
.profile-links {
  list-style: none;
  padding-right: 40px;
  .profile-link {
    font-size: 50px;
    display: inline-block;
    width: 20%;
    text-align: right;
    /*Twitter*/
    .fa-twitter{color:#1da1f2;}
    /*Facebook*/
    .fa-facebook-square{color:#3b5998;}
    /*instagram*/
    .fa-instagram{color:#e1306c;}
  }
}

```

#あとがき

以上で実装まで完了です。
長いことお付き合いいただきありがとうございました。