Progate +α メモず【Ruby on Rails ⑩⑪】


# はじめに

Ruby on Rails ラストです！！
いつものごとくメモの羅列なので、気になる見出しからお読みください。

# メモず

## 「いいね」を新しいテーブルで管理するワケ

- 既存のテーブル`users` `posts` じゃダメなの？
  いいけど、それぞれのテーブルが「いいね」情報で肥大化して、パフォーマンスが落ちるかも。
- 「いいね」を新しいテーブルにするメリット
  - コードロジックが整理され、理解しやすくなる。メンテナンス性も上がる。
    - 例：`if Like.find_by(user_id:@current_user.id, post_id:@post.id)`の`if`文のみで、いいねしている場合、してない場合の挙動を設定できる。
  - テーブルとして独立していると、スケーラビリティが向上する（読み書きの負荷分散・時間や地域によってサーバーを分割・クエリの最適化）。

## `link_to`メソッドの中でアイコンを使うには

```erb
<%= link_to("URL") do %>
	<span class="fa fa_name"></span>
<% end %>
```

このように、`do`を使うとできる。
挙動としては、

> この方法では、link_to メソッドは最初からブロックの存在を認識しており、第一引数を URL として、ブロック内の内容をリンクの表示内容として処理します。

らしい。なんとなく納得はできてない。

### `do`を書くと引数の解釈が変わる、納得できないんだけど

> Q.link_to do について、do を書けば位置引数の示すものが変わるというのは、link_to の特別な仕様ですか？それとも、rails においては比較的一般的な仕様ですか？

> A. `link_to do`の挙動は、Ruby on Rails における特定のヘルパーメソッドに特有の仕様です。これは`link_to`メソッドに限らず、Rails の多くのヘルパーメソッドで見られるパターンです。ブロックを受け取ることで、メソッドの動作や引数の解釈が変わるのは Rails の特徴的な部分です。

> たとえば、`form_for`や`content_tag`などの他のヘルパーメソッドでも、ブロックを使用すると引数の解釈が変わることがあります。これにより、Rails は非常に柔軟なビューの生成を可能にしています。

> このような挙動は、Ruby のブロックを活用した DSL（ドメイン固有言語）の一種と考えることができます。Rails はブロックを使って、より表現力豊かで読みやすいコードを書くことを可能にしています。ブロックを使うことで、より複雑な HTML 構造やフォームを簡潔に、かつ直感的に記述できるようになっています。

> したがって、`link_to do`のような挙動は、Rails のビューヘルパーにおける一般的な仕様と言えます。これは Rails の「設定より規約」の哲学に基づき、一貫した方法でビューを構築するためのものです。

・・・・・・なるほど。
確かに、表現力豊かには書ける。一方で、書き手・読み手の誤解や混乱を招く恐れがあるやり方でもあるな。

## `gem`：多言語でいう、`flamework`/`library`のこと

Rails も`gem`にあたる。
フレームワークとライブラリって、そこまで分ける必要性は少ないし、まとめてるのはいいかも。フレームワークは Rails 一択だし。

### `gem`の使い方

ルートディレクトリ直下の`Gemfile`に`gem 'gem-name', 'version.number'`と記載。`version.number`はオプショナル。
例

```rb
gem 'rails', '5.0.3'
# Use Puma as the app server
gem 'puma', '3.6.2'
# Use SCSS for stylesheets
gem 'sass-rails', '5.0.6'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '3.0.4'
gem 'pry-rails', '0.3.4'
# Use jquery as the JavaScript library
gem 'jquery-rails', '4.2.2'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '5.0.1'
```

その後、ターミナルから`$ bundle install`を実行すると、インストールされる。

## パスワードのハッシュ化`gem`：`bcrypt`

### `has_secure_password`

パスワードを扱うモデルに、このコマンドを追加することでパスワードの安全性を高めてくれる。
具体的には、

- 自動的にパスワードをハッシュ化してくれる。
- 認証時に、そのハッシュ値を検証してくれる。
- パスワードが空でないことを確かめてくれる（`presence`と同じ効果）

### `bcrypt`の使い方・注意

例

```rb
  def login
    @user = User.find_by(email: params[:email])
    if @user && @user.authenticate(params[:password])
      session[:user_id] = @user.id
      flash[:notice] = "ログインしました"
      redirect_to("/posts/index")
    else
      @error_message = "メールアドレスまたはパスワードが間違っています"
      @email = params[:email]
      @password = params[:password]
      render("users/login_form")
    end
  end
```

- `if @user && @user.authenticate(params[:password])`のように、`@user`が存在するか確かめてから使わないといけない。これは、`@user`が存在しない場合、`@user.authenticate`で「存在しないもののさらに内部」にアクセスしようとして、エラーになってしまうため。
- 保存先カラムとして`password_digest`に保存されることになっている。
  `password_digest`カラムが存在しない場合はエラーを返すので注意！！
- `@user.authenticate(params[:password])`の挙動：`params[:password]`を内部でハッシュ化し、`@user.password_digest`と比較して`boolean`（この 2 つは等しいか等しくないか：`true`か`false`か）を返す。

### 雑記：`@user && @user.property`が成り立つわけ = 短絡評価

`@user && @user.property`
このコードの目的は、`@user`が存在することを確かめたうえで、`@user.property`にアクセスするということ。
`@user`が存在しない場合、そのプロパティにアクセスを試みるとエラーが発生してしまうため、それを避けたい。

このコードの倫理構造を言葉にすると「`@user`が存在する（`true`を返す）」かつ「`@user.property`も`true`を返す」。
つまり、「`@user`が存在する」ことと、「`@user.property`が`true`を返す」ことが同時に評価されているように見える。

しかし、同時に評価されてしまうと、このコード（`@user && @user.property`）の目的が果たされない。`@user.property`が実行されてしまい、`@user`が存在しないときエラーが出てしまう。

でも、このコードはエラーにならない。これは、最初の「`@user`」が`false`の場合、そのあとの評価をせず、このコードが`false`を返すため。これを、**短絡評価**と言う。
現在主流の言語は短絡評価を採用、あるいは「結果的に短絡評価を実現」する仕組みになっているため、この記法「最初に存在を確認してから、内部プロパティへアクセスする」は汎用的な書き方。

### 雑記：`digest`は「ダイジェスト」

英単語としての意味は「消化する」。転じて、「要約する」。
ここで`digest`が使われているのは、ハッシュ化（固定長の文字列で表現する）＝要約する＝`digest`ということっぽい。

### 雑記：`crypt`の意味と、IT におけるニュアンス

`crypt`=クリプトっていいですよね。言葉の響きが好き。あと某 FPS のキャラで、そのキャラも好きなんですよね。
キャラクターのクリプト君も、IT に精通している人物に設定されているので、`crypt`は IT において特別で固有のニュアンスをもつはず。

#### 単語としての、もともとの意味

英語の意味：「地下室」「地下納骨堂」
ラテン語の「crypta」・古代ギリシャ語の「κρύπτη (kryptē)」
→「隠れた」という意味の言葉に由来

#### IT における意味

「暗号化」や「セキュリティ」に関連する用語。
「地下室」から転じて「隠す」ニュアンスを持つ。
特に、暗号化を指すことが多い。
「変換する」ニュアンスもあるようだが、これは暗号化に伴うものだろうか。

なんにせよ、

> IT 分野での「crypt」は、データの安全性や秘密保持を高める手段として広く認識されています。

# 終わりに

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Rails終わり！楽しかった～！！！ <a href="https://t.co/SkArRysLb2">pic.twitter.com/SkArRysLb2</a></p>&mdash; たま / SamuraiStats⚾ (@SamuraiStats) <a href="https://twitter.com/SamuraiStats/status/1747021843557654762?ref_src=twsrc%5Etfw">January 15, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

楽しかったです。初の MVC モデルに始まり、初めてクラスをちゃんと使った実装をしたし、納得感を持ってカリキュラム通りにモノを作ったのも初めてでした。

前々から気になってたアイデア、実装できるようになったはず！！
いつやるかは・・・・・・気分ですが・・・・・・
作ったら Qiita で共有します。