この記事ではRails 6.0.0を使用しております。
当方、プログラミング初学者です。
Ruby on Railsにおいて、ActiveHashの学習中に発生したエラーについて
備忘録として残したいと思います。
結論から言うと、単なるスペルミスが原因のエラーでしたが、
エラー表示がパッとでてこなかった場合の、エラーの原因を探す1つの方法を記します。
ActiveHashの学習のために、簡易的な記事投稿アプリを作成しております。
記事の"ジャンル"をActiveHashで表示させるようにします。
ActiveHashの導入方法などは、他の記事を参照してもらうとして、
gem導入後、下記のようにモデル、コントローラー、ビューを作成しました。
class Genre < ActiveHash::Base
self.date = [
{ id: 1, name: '--' },
{ id: 2, name: '経済' },
{ id: 3, name: '政治' },
{ id: 4, name: '地域' },
{ id: 5, name: '国際' },
{ id: 6, name: 'IT' },
{ id: 7, name: 'エンタメ' },
{ id: 8, name: 'スポーツ' },
{ id: 9, name: 'グルメ' },
{ id: 10, name: 'その他' }
]
include ActiveHash::Associations
has_many :articles
end
class Article < ApplicationRecord
extend ActiveHash::Associations::ActiveRecordExtensions
belongs_to :genre
validates :title, :text, presence: true
validates :genre_id, numericality: { other_than: 1 , message: "can't be blank"}
end
class ArticlesController < ApplicationController
def index
@articles = Article.order("created_at DESC")
end
def new
@article = Article.new
end
def create
@article = Article.new(article_params)
if @article.save
redirect_to root_path
else
render :new
end
end
private
def article_params
params.require(:article).permit(:title, :text, :genre_id)
end
end
<%= form_with model: @article, url:articles_path, local: true do |f| %>
<div class="article-box">
記事を投稿する
<%= f.text_field :title, class:"title", placeholder:"タイトル" %>
<%= f.text_area :text, class:"text", placeholder:"テキスト" %>
<%= f.collection_select(:genre_id, Genre.all, :id, :name, {}, {class:"genre-select"}) %>
<%= f.submit "投稿する" ,class:"btn" %>
</div>
<% end %>
Rails.application.routes.draw do
get 'articles/index'
get 'articles/new'
root to: 'articles#index'
resources :articles
end
いざブラウザにて動作確認しようとしたら、
なぜかActiveHashのフォームが空になっており、クリックしてもプルダウンを表示できない…。
上記の通り、バリデーションにて初期値で '--' を表示させる設定にしているのに、それすらも表示されない…。
明らかにおかしいのにエラー文でないし、ヒントになるものがない!
とパニックに陥りかけましたが、まずは状況を整理し、以下の仮説を立てました。
- ビューのform_with以下の記述に間違っている部分がある。
- 空欄になっているということは、genreモデルから情報を取得できていない。
まず、1つ目の仮説を検証します。
ビューを念入りにチェックしますが、スペルなどを間違っている部分は見当たらない…。
次に2つ目の仮説検証のために、他のルーティングや設定したバリデーションやアソシエーションが間違ってないかを確認しますが、
間違っていそうな部分がこの時点では見つけられませんでした…。
もう先人のお知恵を借りるしかないと、ググってみたところ、
こちらの記事( Pikawaka )の中のこの一文に目が止まりました。
試しにコンソールモードでactive_hashのallメソッドを使ってみましょう。
〜中略〜
このようにデータベースに登録してある時と同じ挙動になるのが確認できました。
なるほど。コンソールでデータベースから情報を取得できているか確認すればいいのか!
ということで早速実行してみると一発で原因がわかりました。
% rails c
irb(main):001:0> Genre.all
Traceback (most recent call last):
3: from (irb):1
2: from app/models/genre.rb:1:in `<main>'
1: from app/models/genre.rb:2:in `<class:Genre>'
NoMethodError (undefined method `date=' for Genre:Class)
Did you mean? data=
data
irb(main):002:0>
このように、genreモデルのメソッドが違う気がするよ!
と教えてくれました。
下記のように修正したら、ちゃんと意図した通りにプルダウンできるようになりました。
class Genre < ActiveHash::Base
self.data = [
{ id: 1, name: '--' },
{ id: 2, name: '経済' },
# 以下省略
単純なミスほど見落としがちですので、意図しない挙動をしても
落ち着いて対処できるようになりたいものです。
しかし、'data'と'date'はどうやって使い分けるのだろうか…。
これはまた今度調べようと思います。