LoginSignup
2
1

More than 3 years have passed since last update.

active hashでdbに登録させる時の注意点

Posted at

1 はじめに

active hashについては以下の記事に書いています。

「active hash でセレクトボックスをつくる」

https://qiita.com/DON4024/items/78edb7a309ee96766952

今回は某フリマサイトを作成中に起こった思わぬ動作について書いています。

2 生じた問題

今回のアプリケーションではactive hashで複数のモデルを作成していました。
年、月、日、都道府県、配送方法、配送負担、発送日数などです。
すべて入力必須項目なのでモデルにnull falseのバリデーションをかけていました。

しかし、ユーザー登録の動作を確認中に問題が生じました。
ミスで生年月日を何も選択せずに登録ボタンを押してしまった時です。
バリデーションをかけているので、当然エラーメッセージが出ると思っていたのですが、登録できてしまいました。

すぐに登録先のモデルとマイグレーションファイルを確認。
null falseのバリデーションは問題なく効いていました。

2 原因

1) active hashのコード

以下が使用していた、生年月日の年のactive hashのモデルです。

Birthdayy.rb
class Birthdayy < ActiveHash::Base
  self.data = [
      {id: 0, year: '---'},
      {id: 1, year: '2020'}, {id: 2, year: '2019'}, {id: 3, year: '2018'}, {id: 4, year: '2017'}, {id: 5, year: '2016'}, 
      {id: 6, year: '2015'}, {id: 7, year: '2014'}, {id: 8, year: '2013'}, {id: 9, year: '2012'}, {id: 10, year: '2011'}, 
      {id: 11, year: '2010'}, {id: 12, year: '2009'}, {id: 13, year: '2008'}, {id: 14, year: '2007'}, {id: 15, year: '2006'}, 
      {id: 16, year: '2005'}, {id: 17, year: '2004'}, {id: 18, year: '2003'}, {id: 19, year: '2002'}, {id: 20, year: '2001'}, 
      {id: 21, year: '2000'}, {id: 22, year: '1999'}, {id: 23, year: '1998'}, {id: 24, year: '1997'}, {id: 25, year: '1996'}, 
      {id: 26, year: '1995'}, {id: 27, year: '1994'}, {id: 28, year: '1993'}, {id: 29, year: '1992'}, {id: 30, year: '1991'}, 
      {id: 31, year: '1990'}, {id: 32, year: '1989'}, {id: 33, year: '1988'}, {id: 34, year: '1987'}, {id: 35, year: '1986'}, 
      {id: 36, year: '1985'}, {id: 37, year: '1984'}, {id: 38, year: '1983'}, {id: 39, year: '1982'}, {id: 40, year: '1981'}, 
      {id: 41, year: '1980'}, {id: 42, year: '1979'}, {id: 43, year: '1978'}, {id: 44, year: '1977'}, {id: 45, year: '1976'}, 
      {id: 46, year: '1975'}, {id: 47, year: '1974'}, {id: 48, year: '1973'}, {id: 49, year: '1972'}, {id: 50, year: '1971'}, 
      {id: 51, year: '1970'}, {id: 52, year: '1969'}, {id: 53, year: '1968'}, {id: 54, year: '1967'}, {id: 55, year: '1966'}, 
      {id: 56, year: '1965'}, {id: 57, year: '1964'}, {id: 58, year: '1963'}, {id: 59, year: '1962'}, {id: 60, year: '1961'}, 
      {id: 61, year: '1960'}, {id: 62, year: '1959'}, {id: 63, year: '1958'}, {id: 64, year: '1957'}, {id: 65, year: '1956'}, 
      {id: 66, year: '1955'}, {id: 67, year: '1954'}, {id: 68, year: '1953'}, {id: 69, year: '1952'}, {id: 70, year: '1951'}, 
      {id: 71, year: '1950'}, {id: 72, year: '1949'}, {id: 73, year: '1948'}, {id: 74, year: '1947'}, {id: 75, year: '1946'}, 
      {id: 76, year: '1945'}, {id: 77, year: '1944'}, {id: 78, year: '1943'}, {id: 79, year: '1942'}, {id: 80, year: '1941'}, 
      {id: 81, year: '1940'}, {id: 82, year: '1939'}, {id: 83, year: '1938'}, {id: 84, year: '1937'}, {id: 85, year: '1936'}, 
      {id: 86, year: '1935'}, {id: 87, year: '1934'}, {id: 88, year: '1933'}, {id: 89, year: '1932'}, {id: 90, year: '1931'}, 
      {id: 91, year: '1930'}, {id: 92, year: '1929'}, {id: 93, year: '1928'}, {id: 94, year: '1927'}, {id: 95, year: '1926'}, 
      {id: 96, year: '1925'}, {id: 97, year: '1924'}, {id: 98, year: '1923'}, {id: 99, year: '1922'}, {id: 100, year: '1921'}, 
  ]
end

2) registrationコントローラー new.html.haml

ユーザー登録ページのhamlの記述です。

new.html.haml
= f.collection_select :birthdayy_id, Birthdayy.all, :id, :year

3) userマイグレーションファイルのバリデーション

必須事項にバリデーションをかけています。

devise_create_users.rb

class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      ## Database authenticatable
      ---省略---
      t.integer :birthdayy_id, null: false
      t.integer :birthdaym_id, null: false
      t.integer :birthdayd_id, null: false
      ---省略---
  end
end

4) userモデルのバリデーション

必須事項にバリデーションをかけています。

user.rb
class User < ApplicationRecord
  ---省略---
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :birthdayy
  belongs_to_active_hash :birthdaym
  belongs_to_active_hash :birthdayd

  ---省略---
  validates :birthdayy_id, presence: true
  validates :birthdaym_id, presence: true
  validates :birthdayd_id, presence: true
  ---省略---
end

一見問題なさそうですが、原因はこれでした。
1) Birthdayy.rb'---' のidが 「0
2) devise_create_users.rbでカラムの型をintegerにしている
3) collection_select:idをparamsで送っている

1~3により、何も選択しなかった場合、「0」がcreateアクションに送られたためバリデーションをすり抜けてしまったようでした。

3 解決策

解決方法はいくつかあると思います。

  • 保存させる数字の範囲を指定する
  • integerのうち「0」という数字以外を登録させる
  • '---'を使うのを諦める など

今回は以下の方法を教えてもらったので使用しました。

= f.collection_select :birthdayy_id, Birthdayy.all, :id, :year, prompt: '---'

最後の

prompt: '---'

を記述することで、セレクトタブでは問題なく選択肢に'---'が表示されます。



また、'---'を選択した状態でsubmitを押すと、nullとして送信されるため、null falseでバリデーションに引っ掛かることになるため設定も簡単です。

4、終わりに

チームで開発すると繋がりができて今まで話したことがない人から情報を得られる機会が増えるので大事な期間です。
積極的に他チームの人と繋がりましょう。



以上です。最後までご覧いただきありがとうございました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1