ActiveHashを導入した際のselectメソッドの使用方法


##環境

'rails', '~> 6.0.0'

'capybara', '>= 2.15'

ruby '2.6.5'

##はじめに
systemspecによる結合テストを行なっている際に、トップページレンダーした時に、以下のようなエラーが発生しました。
結論からお話しますと、このエラーはCapybaraのselectメソッドの記述ミスにより発生するものでした。
以下、エラーが発生した記述ではselectメソッドで’法規・条例’という文字をcategoryから探して選択するという記述をしているのですが、
実際の挙動としてはそこで選択した項目のidを引数として、トップページに渡すという作業をしています。

```
undefined method `[]' for nil:NilClass
```
とはselectメソッドで指定すべきidがありませんという内容と想定されます。
そのため、selectメソッドの中に引数となるidの番号を含めて記述しなくてはなりません。

エラーの原因となったコードを見てみますと、

```
select '法規・条例', from: 'tip_category_id'
```
となっておりますが、これをidを含めた形に修正すると、以下のようになります。

```
select Category.data[@tip.category_id - 1][:name], from: 'tip_category_id
```
Categoryモデルから@tipを引数にidを選択する記述に変更しました。
なお、activeHashは０から始まる番号で数字を選択するため、idとの関連性を考慮し、category_id -1 をしております。


##以下、記述内容

エラー本文

```ruby
Failure/Error: <p class="tiped-title-contents">カテゴリー :  <%= Category.data[f.category_id][:name] %></p>
     
     ActionView::Template::Error:
       undefined method `[]' for nil:NilClass
     
     [Screenshot]: /Users/taniguroarata/originalapp/archtips/tmp/screenshots/failures_r_spec_example_groups_nested_nested_visit_new_user_session_path_231.png

     
     # ./app/views/tips/_main_area.html.erb:17:in `block in _app_views_tips__main_area_html_erb__1894181271776908624_70358077282820'
     # ./app/views/tips/_main_area.html.erb:12:in `_app_views_tips__main_area_html_erb__1894181271776908624_70358077282820'
     # ./app/views/tips/index.html.erb:10:in `_app_views_tips_index_html_erb___4391342711310590138_70357992921920'
     # ------------------
     # --- Caused by: ---
     # NoMethodError:
     #   undefined method `[]' for nil:NilClass
     #   ./app/views/tips/_main_area.html.erb:17:in `block in _app_views_tips__main_area_html_erb__1894181271776908624_70358077282820'
```

spec/system/tips_spec.rb

```ruby
require 'rails_helper'

RSpec.describe "投稿する", type: :system do
  before do
    @tip =  FactoryBot.create(:tip)
    @user = FactoryBot.create(:user)
  end

  context '投稿に成功した時' do
    it 'visit new_user_session_path' do
      visit new_user_session_path
      fill_in 'user_email', with: @user.email
      fill_in 'user_password', with: @user.password
      find('input[type="submit"]').click
      expect(current_path).to eq(root_path)
      expect(page).to have_content('新規投稿')
      visit new_tip_path
      fill_in 'tip_title', with: @tip.title

      select '法規・条例', from: 'tip_category_id' #ここがエラーの原因です
      #以下のように修正します
      select Category.data[@tip.category_id - 1][:name], from: 'tip_category_id

      fill_in 'tip_description', with: @tip.description
      binding.pry
      expect{
        find('input[type="submit"]').click
      }.to change {Tip.count }.by(1)
      expect(current_path).to eq(root_path)
    end
  end
end
```

app/views/tips/new.html.erb　（テスト時の画面）

※画像の投稿は必須ではないため、今回は飛ばしてテストしております

```ruby
<div class = "wrapper">
  <%= render "shared/header" %>
  <div class="main-tips-new">
    <div class = "new-tip-string">
      <p>新規投稿</p>
    </div>
    <%= form_with(model: @tip, local: true) do |form| %>
      <%= render 'layouts/error_messages', model: form.object, class:"" %>
      <div class="tip-title">
        <p>タイトル</p>
        <div class="tip-title-content">
          <%= form.text_field :title, placeholder: "" %>
        </div>
      </div>
      <div class="tip-category">
        <p>カテゴリー</p>
        <div class="tip-category-content">
          <%= form.collection_select(:category_id, Category.all, :id, :name, {}, {class:""}) %>　#ここにactiveHashを用いて、番号によって項目を、選択をしております。
        </div>
      </div>
      <div class="tip-images">
        <div class="tip-image-main">
          <p class="tip-image-main-text">画像(メイン)</p>
          <div id="image-list">
            <%= form.file_field :image, class: 'tip-image-main-img' %>
          </div>
        </div>
        <div class="tip-image-sub">
          <p class="tip-image-sub-text">画像（サブ）</p>
          <div class="tip-image-sub-images">
            <%= form.file_field :image, class: 'tip-image-sub-img' %>
            <%= form.file_field :image, class: 'tip-image-sub-img' %>
            <%= form.file_field :image, class: 'tip-image-sub-img' %>
          </div>
        </div>
      </div>
      <div class="tip-description">
        <p class="tip-description-text">説明</p>
        <%= form.text_field :description, placeholder:"", class: 'text-form' %>
      </div>
      <%= form.submit "投稿する" %>
    <% end %>
  </div>
</div>
```



app/models/category.rb

```ruby
class Category < ActiveHash::Base
  self.data = [
    { id: 1, name: '--' },
    { id: 2, name: '法規・条例' },
    { id: 3, name: '納まり・詳細図' },
    { id: 4, name: '仕上げ' },
  ]

  include ActiveHash::Associations
  has_many :categories

  end
```

##終わりに
select等の要素を選択する際にはbinding.pryで値を確認しつつ行うとうまくいくことが多いです。
この記事が皆様のお役に立てればとおもいます。