Ruby on Rails5初学者が一度でもつまずいたところをメモする

## 新しいアプリケーションを立ち上げたい
```ruby
rails new "アプリケーション名"
```
例
```ruby
rails new myapp
```

## railsサーバーを起動する
```ruby
rails server
```

## コントローラーとアクションの作成
```ruby
rails generate controller  "コントローラー名" "アクション名"
```
例
```ruby
rails generate controller home top
```
そうすると以下のものが生成される
```bash
      create  app/controllers/home_controller.rb
       route  get "home/top" => "home#top"
      invoke  erb
      create    app/views/home
      create    app/views/home/top.html.erb
      invoke  rspec
      create    spec/controllers/home_controller_spec.rb
      create    spec/views/home
      create    spec/views/home/top.html.erb_spec.rb
      invoke  helper
      create    app/helpers/home_helper.rb
      invoke    rspec
      create      spec/helpers/home_helper_spec.rb
      invoke  assets
      invoke    js
      create      app/assets/javascripts/home.js
      invoke    scss
      create      app/assets/stylesheets/home.scss
```
- app/controllers/home_controller.rb
    - homeコントローラー用のrbファイル(MVCのC)
- app/views/home/top.html.erb
    - homeコントローラーのビュー用のrbファイル(MVCのV)
- spec/controllers/home_controller_spec.rb
    - 何に使うかまだ分からん
- spec/views/home/top.html.erb_spec.rb
    - 何に使うかまだ分からん
- app/helpers/home_helper.rb
    - 何に使うかまだ分からん
- spec/helpers/home_helper_spec.rb
    - 何に使うかまだ分からん
- app/assets/javascripts/home.js
    - おそらくhomeコントローラー用のjs記載用
- app/assets/stylesheets/home.scss
    - homeコントローラー用のcss記載用

実行するとconfig/routes.rb ファイルにルーティングが追加される
```ruby
  get "home/top" => "home#top"
```
get "home/top" => "home#top"の`"home#top"` の部分はhome_controller.rb ファイル内の HomeController クラスに def top というメソッドがあるという意味です。

## HTMLでlink_toメソッドを使用してのリンクの生成
```ruby
<%= link_to "表示文字列", "uri" %>
```
例
```ruby
<%= link_to "Go to Top", "/home/top" %>
```

## モデルとマイグレーションファイルの同時作成コマンド
```bash
rails g model テーブル名（単数形） カラム名:データ型
```
例: content: text以降は複数の選択が可能
```bash
rails g model posts content:text
```

マイグレーションファイルの中身をデータベースに反映するには以下のようにする
```
rails db:migrate
```
以下の手順でテーブルにデータを保存する
1. `rails console`コマンドを実行
2. モデルのインスタンスを作成
    post = Post.new(引数)
3. saveメソッドを用いて、作成したインスタンスを保存
    post.save
6.quit で終了

上記のコマンドだとモデルとマイグレーションが同時に作成される。
もしマイグレーションファイルのみを作成したい場合は以下のコマンドを実行する
```bash
rails g migration {ファイル名}
```
実行するとファイル名のマイグレーションファイルが作成される。
自由に指定できるが追加するカラム名を含めるなどわかりやすい名前が望ましい。

## コントローラーのみを作成
```bash:書き方
$ rails g controller コントローラ名
```
```bash:例[bash]
$ rails g controller homes
```

## マイグレーションファイルの仕組み
空のマイグレーションファイルを作成した際にテーブルへ変更を加えるためには
changeメソッドの中に変更内容を書く必要がある。
`rails db:migrate`コマンドはこのchangeメソッドの中身を実行するためのコマンドである。
主導で書く場合は以下のように記述する
```text
    def change
        add_column :テーブル名, :カラム名, :データ型, :デフォルト値
```
```ruby
    def change
        add_column :users, :image_name, :string, default: 'default_user.jpg'
```

なおカラムを削除する場合は`remove_column`で記載する

## コントローラークラスでのDBの操作
1.データベースレコードの作成 (create) と保存 (save)
```ruby
post = Post.new(title: "New Post", content: "Lorem ipsum...")
post.save
```

2.データベースからのレコードの検索 (find, find_by):
```ruby
post = Post.find(1)
post = Post.find_by(title: "Some Title")
```

3.データベースレコードの更新 (update, update_attributes):
```ruby
post = Post.find(1)
post.update(title: "Updated Title")
# または
post.update_attributes(title: "Updated Title", content: "New content")
```
4.データベースレコードの削除 (destroy, delete):
```ruby
post = Post.find(1)
post.update(title: "Updated Title")
# または
post.update_attributes(title: "Updated Title", content: "New content")
```
### allメソッド
- where: 特定の条件に基づいてレコードを絞り込むために使用します。

- limit: 取得するレコードの数を制限します。

- select: 特定のカラムだけを選択して取得します。

あとはallで取得してforで取り出すなどが良くつかわれる。

### DBから削除
```ruby
post = Post.find_by(id: 2)
post.destroy
```

## paramsとは何か
```ruby
@post = Post.find_by(id: params[:id])
```
というときに出てきたparamsというは何か？
⇒Railsコントローラー内でアクションがリクエストを受け取る際に使用されるハッシュ。
具体的には、params[:id] の部分は、URL内のパスの一部として渡された :id パラメータを指します。


## updateのときのrouter.rb
```rb
post "posts/:id/update" => "posts#update"
```
getではなくpostにする必要がある

## リダイレクトの書き方
`redicret_to("/posts/index")`

## updateのときのrouter.rb
```rb
post "posts/:id/update" => "posts#destory"
```
getではなくpostにする必要がある

## link_toを用いてdestroyアクションを行うときの注意点
link_toを普通に書くとget用のルーティングを探してしまう。そのため
post用に以下のように変更する
```ruby
<%= link_to(表示名, URL, {method: "post"}) %>
```

## バリデーションの書き方
```text:書き方
class Post < ApplicationRecord
    validates: 検証するカラム名, {検証する内容(, で区切ることで複数指定できる)}
```

presence ⇒カラムの値が存在するかどうか
他の詳細は以下
[Active Record バリデーション \- Railsガイド](https://railsguides.jp/active_record_validations.html#presence)

```ruby:例
class Post < ApplicationRecord
    validates :content, {presence: true}
```
他のバリデーションは以下
[Active Record バリデーション \- Railsガイド](https://railsguides.jp/active_record_validations.html)

## コロンの位置による書き方の違いについて
上記のバリデーションの書き方でコロンの位置が違うことでミスったので記載
```ruby
validates :content, presence: true, length: { maximum: 50 } 
```
とあると
```text
:content  
→先頭にコロンがあるのでシンボル！

presence: true
→validatesメソッドの引数部分で後ろコロンなのでキーワード引数
 presence:というキーワード引数は、trueですよって渡してる（presenceという見出しをつけてる）

length: 
→validatesメソッドの引数部分で後ろコロンなのでキーワード引数

{ maximum: 50 }
→波括弧があるからこれはハッシュ
 ハッシュの内側で後ろコロンは、シンボルをキーにしたハッシュ。
```
シンボルとは
文字列の上位版。シンボルは重複が許されずシンボルの中身が同じであればコンピューター内部では1か所に
保存され処理速度がちょっと早くなる

[参考: Rubyの:\(コロン\)の種類 \#Ruby \- Qiita](https://qiita.com/mdgwshk2021/items/5517afe1195d713b6f70)

## renderとredict_toの違い
redict_to ⇒別のアクションに移動
render ⇒　アクションを経由せずに直接ビューに表示
```ruby
redirect_to(URL) #URLなので/hogehoge/piyopiyoみたいに書く
render("フォルダ名/ファイル名") #ビューファイルを指定する。なので/で始まらない
```

## フラッシュを表示したい
```ruby
flash[:notice] = "表示したい文字列"
```

## form_tagの書き方
```erb
<%= form_tag("/posts/create", method: "post") do %>
  <!-- フォームの中身 -->
<% end %>
```
- Railsはセキュリティ対策やリクエストの送信先URLなどを考慮して、フォームを生成
- ただし新しいRailsだとform_withを使用することが推奨される
:::note info
link_toメソッドではデフォルトでgetのルーティングを探し、form_tagメソッドがデフォルト
でpostのルーティングを探してます。
:::


画像の送信は特殊なので、form_tagに{multipart: true}を追加する必要がある。
```erb
<%= form_tag("...", {multipart: true}) do %>
```

## Rubyでのファイル保存
Rubyのコードでファイルを扱うには、Rubyに元から用意されているFileクラスを用いる。

### ファイル作成
```
$rails console
File.write("ファイルの場所", "ファイルの中身")
```
画像データの場合は特殊なテキストファイルであるため、
File.writeではなくFile.binwriteを用いる
```ruby:書き方
File.binwrite("フォイルの場所", "ファイルの中身(画像データ)")
```

```ruby:例
File.binwrite("public/user_images/#{@user.image_name}", image.read)
```
## Session
ページを移動してもユーザ情報を保持し続けるために、sessionという特殊な変数を用いる
```
session[:キー名] = 値
```
```ruby
session[:user_id] = @user.id
# 特定したユーザのidを代入することで、
# ログインユーザの情報を保持することができる
```
こうすることでページを移動しても値を保持され続ける
なおログアウト実施時は以下のようになる
```ruby
# パターン1
session[:user_id] = nil

# パターン2
session[:user_id].clear
```
項目を指定しないとすべてのセッションが無くなる。
session内のキー名はなんでも自由に設定可能
参考: [【Rails】Sessionの使い方について \#初心者 \- Qiita](https://qiita.com/ozackiee/items/4ee774c81b2a0c571c05)





## 各コントローラーの全アクション共通する処理がある場合
`before_action`は**アクションを実行する前に特定の処理を実行**する

```ruby:書き方
before_action # 全アクションで共通する処理
def index
    @current_user
end
def show
    @current_user
end
```

```ruby:例
before_action :set_current_user
def set_current_user
    @current_user
end
```
以下のようにアクションを指定することで指定したアクションのみを実行することができる。
```ruby
before_action :set_current_user,{only: [:edit, :update]}
```
各コントローラーはapplicationコントローラーを継承しているため、継承元のメソッドを使うことができる。

before_actionは以下のようなオプションが存在する

| オプション| 意味 | 
| - | - |
| :only | 適用したいアクションを指定 |
| :expect | 適用しないアクションを指定 |
| :if | 適用する条件を指定 |
| :unless | 適用しない条件を指定 |

## whereメソッド
ある条件に合致する「複数の」データを取得するには、whereメソッドを用いる必要がある。

## railsでdo構文の意味
`do`構文はブロック構文と呼ばれる機能の一部です。これは複数の行にわたる処理をまとめて記述し、コードをより読みやすく、簡潔に表現するために使用される
Pythnで例えるとwithステートメントと似ている。
```python
# ファイルを開き、内容を読み込み、閉じる
with open('my_file.txt', 'r') as f:
    contents = f.read()
    print(content
```

## パスワードのハッシュ化
パスワードのハッシュ化はgemというツールを用いて行う
Railsにはインストールしたいgemを記述するGemfileというファイルが存在する。
インストールするgemを記載し`bundle install`コマンドを実行してgemをインストールする。
```ruby:Gemfile
gem 'bcrypt'
```
コントローラーなどに以下のように記載することでpasswordが存在するかを自動的にチェックしてくれる
```ruby:例
class User < ApplicationRecord
  # has_secure_passwordメソッドを追加してください
  has_secure_password
```
`has_secure_passwordメソッド`を使用すると`authenticateメソッド`が使えるようになる。
`authenticateメソッド`は渡された引数をハッシュ化しpassword_digestの値と一致するかどうかを判定する。
```ruby
@user.authenticate(params[:password])
```

## その他
### 使えそうなメソッド名
- 認証ユーザ化の確認
    - `authenticate_user`
- ログイン済みのユーザ化の確認
    - ※forbid = 禁止する
    - forbid_login_user