プルダウン(セレクトボックス)を使おう　-投稿先を選択する-

大学生が集まるプログラミングコミュニティ
GeekSalon(https://bit.ly/2M64LXd) 名古屋メンタ－の吉田です。

・**セレクトボックスでカラムに入れるものを選択したい！**
・**投稿先をindexだけじゃなく、複数のページにも出来るようにしたい！**
とういう人のための記事です。また
・**投稿ボタンを押した後、セレクトした先にすぐ飛びたい！**
というわがままな要望も[応用]として解決法を載せています。
是非参考にして下さい

##まずはセレクトボックスをつけてみよう


こちらの記事を参考につけてみて下さい(丸投げ)
https://qiita.com/kawakami_shotaro/items/11a677bf34136cb7686d

##ゴール：複数のページに投稿出来るようにする
今回はユーザーが「和食・洋食・中華」の3つのジャンルから投稿先を選択するという機能を実装してみます。
![](http://res.cloudinary.com/dzsu5uey2/image/upload/v1601658839/gnatdbevamjpbu15k8ly.jpg)
![](http://res.cloudinary.com/dzsu5uey2/image/upload/v1601658850/sjdhgfbixbdbdpbysohh.jpg)
##用意するもの
* tweetsテーブルのgenreカラム(命名は自由です)
* viewページ(今回はpage1,page2,page3を用意)

まずはこの2つを用意しましょう

コマンドプロンプトを開きtweetsテーブルにgenreカラムを追加していきましょう。自分のプロダクトの階層にcdして

```ruby:コマンドプロンプト
rails g migration AddGenreToTweets genre:integer
rails db:migrate
```

カラムを追加=>データベースに変更を加える=>migrateでしたね。カラムの用意はこれで完了です(保存形式がintegerの理由は後ほど)

viewページはVScodeで3つパパッと作ってしまいましょう。名前はpage1,page2,page3と適当につけておきます(忘れた人は教材で確認！)

##本題：投稿先をindexだけじゃなく、複数のページにも出来るようにする
では実装するためのコードを書いていきましょう。投稿ページのプルダウンのコードはこんな感じです

```ruby:new.html.erb
<%= stylesheet_link_tag 'new', :media => "all" %>

<div class="post-container">
    <p class="title">投稿フォーム</p>
    <%= form_for(@tweet, :url => { controller:'tweets', action:'create'})do |f| %>
    <%= f.label :投稿内容 %>
    <br>
    <%= f.text_field :body,size: 140%>
-----ここから変更-----
    <%= f.select :genre, [["和食", 1], ["洋食", 2], ["中華", 3]], include_blank: "選択して下さい" %>
-----ここまで------
    <div class="field">
      <%= f.label :画像選択 %>
      <%= f.file_field :image %>
    </div>
    <br>
    <%= f.submit "送信" %>
    <br>
    <% end %>
</div>
```

表示は和食ですが、実際カラムに入ってるのは1という風にしています(なので保存形式をintegerにしました)

次はコントローラーを変更しましょう

```ruby:tweets_controller.rb
*省略*
    def page1
    @washokus = Tweet.where(genre: 1)
    end
    def page2
    @yoshokus = Tweet.where(genre: 2)
    end
    def page3
    @chukas = Tweet.where(genre: 3)
    end
*省略*
    private
    def tweet_params
        params.require(:tweet).permit(:body,:image,:genre)
    end
```

順に見ていきましょう

```ruby:tweets_controller.rb
    def page1
    @washokus = Tweet.where(genre: 1)
    end
```

これは「genreカラムに1が入っているものだけを@washokusに代入」しています
この@washokusをpage1のviewで使うことで和食の投稿のみ表示されるように出来ます

```ruby:tweets_controller.rb
    private
    def tweet_params
        params.require(:tweet).permit(:body,:image,:genre)
    end
```

genreカラムに入れたものを運べるよう、ストロングパラメーターにgenreを追加しましょう。これ結構忘れがちです

続いてルーティングを設定しましょう

```ruby:routes.rb
  get 'tweets/page1' => 'tweets#page1'
  get 'tweets/page2' => 'tweets#page2'
  get 'tweets/page3' => 'tweets#page3'
```

余談ですが、ルーティングを書く際はidを扱うコードより上にこれらのコードを書くようにしましょう
(例：`get 'tweets/:id' => 'tweets#show', as: 'tweet'`)
これはidにurlが入ってエラーになるのを防ぐためです

最後にviewページを作ってあげましょう

```ruby:page1.html.erb
<%= stylesheet_link_tag 'index', :media => "all" %>
<h1>和食</h1>
<div class="tweets-container">
<% @washokus.each do |t| %>
    <div class="tweet">
      <%= link_to t.user.name, user_path(t.user.id) %>
      (♡<%= t.liked_users.count %>)
      <% if t.image.present? %>
        <%= image_tag t.image_url, :size => "500x300" %>
      <% end %>
      <div class="main-box">
        <div class="left-container"><%= t.body %></div>
        <div class=right-container>
          <%= link_to "詳細", tweet_path(t.id) %>
          <% if current_user.id == t.user.id %>
            <%= link_to "編集", edit_tweet_path(t.id) %>
            <%= link_to "削除", tweet_path(t.id), method: :delete %>
          <% end %>
        </div>
      </div>
      <p class="time"><%= t.created_at %></p>
    </div>
  <% end %>
</div>
```

```ruby:page2.html.erb
<%= stylesheet_link_tag 'index', :media => "all" %>
<h1>洋食</h1>
<div class="tweets-container">
<% @yoshokus.each do |t| %>
    <div class="tweet">
      <%= link_to t.user.name, user_path(t.user.id) %>
      (♡<%= t.liked_users.count %>)
      <% if t.image.present? %>
        <%= image_tag t.image_url, :size => "500x300" %>
      <% end %>
      <div class="main-box">
        <div class="left-container"><%= t.body %></div>
        <div class=right-container>
          <%= link_to "詳細", tweet_path(t.id) %>
          <% if current_user.id == t.user.id %>
            <%= link_to "編集", edit_tweet_path(t.id) %>
            <%= link_to "削除", tweet_path(t.id), method: :delete %>
          <% end %>
        </div>
      </div>
      <p class="time"><%= t.created_at %></p>
    </div>
  <% end %>
</div>
```

```ruby:page3.html.erb
<%= stylesheet_link_tag 'index', :media => "all" %>
<h1>中華</h1>
<div class="tweets-container">
<% @chukas.each do |t| %>
    <div class="tweet">
      <%= link_to t.user.name, user_path(t.user.id) %>
      (♡<%= t.liked_users.count %>)
      <% if t.image.present? %>
        <%= image_tag t.image_url, :size => "500x300" %>
      <% end %>
      <div class="main-box">
        <div class="left-container"><%= t.body %></div>
        <div class=right-container>
          <%= link_to "詳細", tweet_path(t.id) %>
          <% if current_user.id == t.user.id %>
            <%= link_to "編集", edit_tweet_path(t.id) %>
            <%= link_to "削除", tweet_path(t.id), method: :delete %>
          <% end %>
        </div>
      </div>
      <p class="time"><%= t.created_at %></p>
    </div>
  <% end %>
</div>
```
あとはこれらのページに飛べるよう、適当にリンクをindexに貼っておきましょう

```ruby:index.html.erb
<%= link_to '和食', :controller => "tweets", :action => "page1" %>
<%= link_to '洋食', :controller => "tweets", :action => "page2" %>
<%= link_to '中華', :controller => "tweets", :action => "page3" %>
```

これで完成です！お疲れ様でした！

##[応用]投稿ボタンを押した後、セレクト先にすぐ飛ぶ機能
今のtweetsコントローラーはcreateアクションで

```ruby:tweets_controller.rb
   if @tweet.save
      redirect_to :action => "index"
```

となっているので、投稿後はindexに飛ぶようになっています。これを変更します

```ruby:tweets_controller.rb
    def create
        @tweet = Tweet.new(tweet_params)
        @tweet.user_id = current_user.id
        if @tweet.save and @tweet.genre == 1
            redirect_to :action => "page1"
        elsif @tweet.save and @tweet.genre == 2
            redirect_to :action => "page2"
        elsif @tweet.save and @tweet.genre == 3
            redirect_to :action => "page3"
        else
            redirect_to :action => "index"
        end
    end
```

A and Bは「AかつB」という条件を指します。つまりこの場合「"@tweetが保存される"かつ"genreカラムが1と合致する"」という条件を満たした場合、page1アクションが実行され、その結果page1にそのまま飛ぶようになっています。

セレクトボックスで何も選択しなかったり、保存に失敗した場合はindexに飛ぶようになってますね。