devise導入からフラッシュ実装②


#最初に行うコマンド
deviseをインストールする
#
```
rails g devise:install
```
userモデルを作る。ユーザー管理に必要なため
#
```
rails g devise user
```
いつもの
#
```
$ rails db:migrate
```

ヘッダーをいじります。新規登録とログインとログアウトのリンクを作る
#
```
          = link_to 'ログアウト', destroy_user_session_path, method: :delete, class: 'header__top__userMenu--logout'
        - else
          = link_to '新規登録', new_user_registration_path, class: 'header__top__userMenu--logout'
          = link_to 'ログイン', new_user_session_path, class: 'header__top__userMenu--logout'
```

未ログインのアクセス制限
#
```
before_action :move_to_index, except: [:index]

private
  def move_to_index
    redirect_to action: :index unless user_signed_in?
  end
```
deviseのコマンドでビューを作る
#
```
rails g devise:views
```

#サインアップ時にニックネームを登録
userテーブルにカラムを追加
#
```
rails g migration AddNicknameToUsers nickname:string
```
最大文字数のために
#
```
     <div class="field">
        <%= f.label :nickname %> <em>(6 characters maximum)</em><br />
        <%= f.text_field :nickname, autofocus: true, maxlength: "6" %>
      </div>

```
を追加

ニックネームカラムを送れるようにする
devise_parameter_sanitizerはrequireみたいな意味らしい
#
```
application_controller.rb

  before_action :configure_permitted_parameters, if: :devise_controller?

  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
  end
```

tweetsカラムにuser_idを追加する
#
```
rails g migration AddUserIdToTweets user_id:integer
```

ツイート投稿時にユーザーidを追加
#
```
.merge(user_id: current_user.id)
```

#アソシエーションの定義
1，モデルクラスにhas_many ~~sやbelongs_to ~~(単数形)で関係が定義されてる
2，所属する側のテーブルに「所属するモデル名_id(例）tweet_id」というカラムがある
#
```
has_many :tweets
belongs_to :user
```
#マイページの作成
１．マイページのルーティングを記述しよう
２．マイページへのリンクを作成しよう
３．コントローラーとアクションを作成しよう
４．マイページ用のビューファイルを作成しよう
```
  resources :users, only: :show
= link_to current_user.nickname, user_path(current_user.id)
```
Usersコントローラーを作成
#
```
rails g controller users

  def show
    @nickname = current_user.nickname
    @tweets = current_user.tweets
  end
```

ツイート一覧画面にニックネームを表示
１．投稿者名を表示するようにビューを変更しよう
２．ツイートからユーザー情報を先読みしよう
３．投稿画面のビューを変更しよう
４．投稿時のコントローラーでの処理を変更しよう
includes(:user)を使ってincludesを解消

ログインユーザーのみ編集削除が可能にする
orderメソッドで。
#
```
@tweets = Tweet.includes(:user).order('updated_at desc')
```

#ページネーションの実装
kaminariをbundle install
🔳pageメソッド
paramsの中にpageキーが追加される。引数はparams[:page]
🔳parメソッド
1ページあたりに表示する件数を指定
🔳paginateメソッド
ページネーションのリンクを表示するメソッド

#
```
@tweets = Tweet.includes(:user).order('updated_atdesc').page(params[:page]).per(5)  
<%= paginate(@tweets) %>
```

#コメント機能
#
```
$ rails g model comment
```
マイグレーションファイルを編集してrails db:migrate
アソシエーションとroutesの設定
#
```
$ rails g controller comments

  def create
    Comment.create(comment_params)
  end

  private
  def comment_params
    params.require(:comment).permit(:text).merge(user_id: current_user.id, tweet_id: params[:tweet_id])
  end
```
詳細ビューにコメント投稿フォームと一覧を変更
#
```
   <%= form_with(model: [@tweet, @comment], local: true) do |form| %>
        <%= form.text_area :text, placeholder: "コメントする", rows: "2" %>
        <%= form.submit "SEND" %>
```
showアクションにコメントを追加（超大事、comment定義してなくて1時間こけた）
#
```
  def show
    @comment = Comment.new
    @comments = @tweet.comments.includes(:user)
  end
```
#検索機能の実装（2種類あり）
①collectionを使う

tweetにネストしてルーティングの設定
#
```
  collection do
      get 'search'
    end
```
form_withで検索するフォームを作る

tweetモデルに検索するメソッドを作成
#
```
  def self.search(search)
    if search
      Tweet.where('text LIKE(?)', "%#{search}%")
    else
      Tweet.all
    end
  end
```
tweetsコントローラにsearchアクションを定義
#
```
  def search
    @tweets = Tweet.search(params[:keyword])
  end
```
検索結果のビューを表示
#
```
  <% @tweets.each do |tweet| %>
    <%= render partial: "tweet", locals: { tweet: tweet } %>
  <% end %>
```

②namespaceを利用した方式(⑦つのアクションのみ使用）
searchesコントローラーを作成
#
```
$ rails g controller tweets::searches
```
namespaceのルートを追加する
resouece :tweetsより上に書くこと。
ルートの順番の問題。tweetsのルートが先に読まれておかしくなるから
#
```
  namespace :tweets do
    resources :searches, only: :index
  end
```

検索フォームを追加する
#
```
<%= form_with(url: tweets_searches_path, local: true, method: :get, class: "search-form") do |form| %>
 <%= form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input" %>
  <%= form.submit "検索", class: "search-btn" %>

```
searchコントローラーにindexアクションを追加する
#
```
  def index
    @tweets = Tweet.search(params[:keyword])
  end
```
tweetモデルに検索するメソッドを作成
#
```
  def self.search(search)
    if search
      Tweet.where('text LIKE(?)', "%#{search}%")
    else
      Tweet.all
    end
  end
```

検索結果フォームを追加
#
```
 <% @tweets.each do |tweet| %>
    <%= render partial: "tweets/tweet", locals: { tweet: tweet } %>
  <% end %>
```

#フラッシュメッセージの実装
①フラッシュメッセージが表示されるようにする
②フラッシュメッセージのスタイリングを行う
③フラッシュメッセージを日本語化する

app/views/layouts/_notifications.html.haml
#
```
.notification
  - flash.each do |key, value|
    = content_tag :div, value, class: key
```