link_toメソッドを使った範囲リンクとネストした個別リンクの実装方法

この記事はプログラミング学習者がアプリ開発中に躓いた内容を備忘録として記事におこしたものです。内容に不備などあればご指摘頂けると助かります。

#### link_toメソッドを使って範囲リンクと複数のlink_toをネストさせてそれぞれのリンクを設置する

この記事ではWebサービス(Xのクローンサイト)を作成中に遭遇したちょっとした壁？についてお伝えしています。

Webサービス上で他のページへのリンクを貼る際にlink_toメソッドは皆さんお使いになると思います。

以下はリンクのサンプル画像とサンプルコードです。

`ホーム`のところにカーソルを合わせてクリックすれば`root_path`へのリンクにアクセスできます。

![スクリーンショット 2024-09-12 20.18.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508918/dcc486de-01ce-f2d8-0814-dc8595d1a56f.png)

```ruby:_nav.html.slim
    ul
      li  = image_tag('house.png', size: '30x30')
      li.logo_name  = link_to 'ホーム', root_path, class: 'link'
```

###### 今回は本家(X 旧Twitter)と同じ様に投稿文などにカーソルを合わせたら投稿詳細ページへのリンクができるようにした内容をご紹介します。

![Xクローンサイト画面遷移正常.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508918/38a3690e-30ed-5d75-445c-700bea8b7f19.gif)


```ruby:index.html.slim
      div class="#{'show active' if params[:tab] == 'recommend'} tab-pane fade " id="for-you"
        - @tweets.each do |tweet|
          = link_to tweet_path(tweet.id) do
            ul
              li
                icon_link = link_to image_tag(tweet.user.icon, alt: "Icon image", class: "icon_image", size: '50x50'), profile_path(tweet.user.id)
              li 
                user_link = link_to tweet.user.name, profile_path(tweet.user.id), class: 'link'
              li 投稿日： #{tweet.created_at.strftime('%Y/%m/%d %H:%M:%S')}
            p = tweet.content
            - if tweet.images.attached?
              - tweet.images.each do |tweet_image|
                = image_tag tweet_image, size: '250x200', class: "tweet_image"
          end
          hr
        = paginate @tweets, :param_name => 'recommend', params: {tab: 'recommend'}, theme: 'twitter-bootstrap-4'
```

##### コードの解説
- 概略説明としては投稿内容をデータベースから取得して`@tweets`インスタンス変数に代入しています。
`@tweets`をeach文で１つずつ展開して内容を表示させるコードとなっています。
- 本家(X 旧Twitter)と同様に本文などに詳細ページへのリンクを持たせるために`= link_to tweet_path(tweet.id) do 〜 end`のブロックで全体を囲っています。
こうすることで投稿日、本文、添付画像などの範囲がリンクの対象になり、詳細ページへ遷移できます。
また、アイコン画像とユーザー名の部分は全体を囲んでいるリンクとは別のページへのリンクを設置しています。
```ruby:index.html.slim(抜粋)
icon_link = link_to ...
user_link = link_to ...
```
link_toで生成されたリンクをそれぞれの変数に代入するように実装しました。
これにより、生成されたリンクは各変数に代入されて、その結果がHTMLとしてレンダリングされるので、変数名が表示される部分のみがリンクになります。
外側の`link_to`はそのまま保持され、他の要素をリンク対象にしますが、link_toを代入している変数部分だけは内部の個別リンクが優先されるため、外部リンクの影響を受けません。
link_toがネストされている場合、内側のリンクが優先されます。そのため、変数で生成されたリンクは外側のリンクに影響されずに独立したリンクとして機能します。


## ちなみに・・・実装当初は下記のコードでした。

![Xクローンサイト画面遷移異常.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3508918/9b6c2d6c-8d9d-04ee-7bbd-466ebbe4fd24.gif)


```ruby:index.html.slim(実装当初)
      div class="#{'show active' if params[:tab] == 'recommend'} tab-pane fade " id="for-you"
        - @tweets.each do |tweet|
          = link_to tweet_path(tweet.id) do
            ul
              li
                 = link_to image_tag(tweet.user.icon, alt: "Icon image", class: "icon_image", size: '50x50'), profile_path(tweet.user.id)
              li 
                 = link_to tweet.user.name, profile_path(tweet.user.id), class: 'link'
              li 投稿日： #{tweet.created_at.strftime('%Y/%m/%d %H:%M:%S')}
            p = tweet.content
            - if tweet.images.attached?
              - tweet.images.each do |tweet_image|
                = image_tag tweet_image, size: '250x200', class: "tweet_image"
          end
          hr
        = paginate @tweets, :param_name => 'recommend', params: {tab: 'recommend'}, theme: 'twitter-bootstrap-4'
```
##### コードの解説
上記のコードですと全体を囲んだリンクの中にリンクをネストさせた形になっています。
HTMLの使用上、リンクがネストされると片側のリンクが無効になります。
今回の場合は外側で囲んでいるリンクが無効となり、ネストした内側のリンクだけ有効になりました。


最後まで読んで頂きありがとうございます。
読まれた方のお役に少しでも立てれば幸いです。

参考にしたサイト
[【Rails】link_toメソッドの使い方](https://qiita.com/ksmj/items/3b4277e3b53376bf943e)