こんにちは。 マネーフォワードのわり算グループでインターンをしている小野直人です。
今回の記事ではタイトルにもある通り、rakeコマンドを打つことでRailsのActiveRecordのバリデーションを自動で書いてくれるgemについて紹介したいと思います。 https://github.com/ono-max/spicy_validation
gemを作った背景
僕の頂いたタスクで「与えられた仕様に沿ってモデルファイル・テーブル定義をする(マイグレーションファイルを書く)」というものがありました。この時に作るモデルファイルやマイグレーションファイルの量が多く、以下の課題感を持ちました。
- 内向きな課題:単純作業なので途中で飽きてしまいそう
- 外向きな課題:ケアレスミスを指摘する手間をレビュアーにかけたくない・効率的にミスなくやりたい
そこでこれらの解決策として自動化するgemを作ってみようと考えました。どこを自動化すべきか考えるために自分が普段モデルファイル・テーブル定義をする上でどのようなコマンドを打ちどのようにコードを書くのか考えてみることにしました。
- 個別モデル・テーブル定義作成 -> modelファイル・migrationファイル作成
rails g model モデル名 hoge:string, foo:integer
-> ここはコマンド1つでできるので問題なさそう
- テーブル定義の更新(&ローカルへ反映) -> schema.rb更新
rails db:migrate
-> ここもコマンド1つでできるので問題なさそう
- 制約に合わせたバリデーション追加 -> modelファイルを編集
- 手修正 -> modelファイルを編集するのはケアレスミスが出そう
このようにプロセスを考えてみるとmodelファイルを編集を自動化できると良さそうだと方針が立ちました。
設計コンセプト
設計コンセプトは以下の通りです。
- いつでも消せるgem
- チーム内で共通して使う必要がないようにしたいのでディレクトリを作り新規作成...ではなく、モデルファイルを書き換える形にする
- validationメソッドを書いてくれるgemを探した時に
app/validators
のようにディレクトリを作りvalidationメソッドを書くgemを見つけた。しかし、このようにディレクトリを作ると今後もチームでこのgemを使い続けなければならない or この書き方に合わせた形でvalidationメソッドを書き続けるという事態が起こってしまうと考えたので直接モデルファイルを書き換える形にした。 - このgemを使うかどうか議論せずに気軽に使って欲しい
- validationメソッドを書いてくれるgemを探した時に
- チーム内で共通して使う必要がないようにしたいのでディレクトリを作り新規作成...ではなく、モデルファイルを書き換える形にする
- 既存のリポジトリでも使えるように
- 自分が書き換えたいモデルファイルだけ書き換えられるようにテーブルを表示->ユーザーに選んでもらうようにした
gemについて
gemを使うまでの流れ
# modelファイルとmigrationファイルを作る(modelファイルはあとで作られるのでDBスキーマにmigrationを行うmigrationファイルさえあれば良い) % rails g model User invoke active_record create db/migrate/20210405034238_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml # DBスキーマのMigrationを行う % rails db:migrate == 20210405034238 CreateUsers: migrating ====================================== -- create_table(:users) -> 0.0019s == 20210405034238 CreateUsers: migrated (0.0019s) ============================= # ActiveRecord::Base.connectionで読み込んだDBスキーマのカラム情報を基にvalidationメソッドをモデルファイルに書く % rails validation:generate [warning] If you generate validation, model files will be overwritten. {:"0"=>"users"} Type a number you wanna generate validation >
イメージ
以下のテーブル情報からvalidationメソッドを作った場合のイメージです。
+------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | bigint(20) | NO | PRI | NULL | auto_increment | | name | varchar(255) | NO | | NULL | | | message | varchar(255) | YES | | NULL | | | age | int(11) | NO | | NULL | | | score | int(11) | YES | | NULL | | | premium | tinyint(1) | YES | | NULL | | | created_at | datetime(6) | NO | | NULL | | | updated_at | datetime(6) | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+
# app/models/user.rb class User < ApplicationRecord validates :name, presence: true validates :age, presence: true, numericality: true validates :score, numericality: true, allow_nil: true end
フォルダ構成
フォルダ構成は以下の通りです。
|─ lib |─ spicy_validation |─ monkey | └─ new_hash_syntax.rb ... hashへのメソッドアクセスをしている |─ railtie.rb ... rakeタスクを読み込んでいる |─ renderer.rb ... ファイルの読み書き・ユーザーからinputを受け取る |─ schema.rb ... DBと接続している |─ tasks | └─ validation.rake ... rakeタスクが定義されている |─ validation.rb ... validationメソッドが作られる └─ spicy_validation.rb ... ファイルをrequireするところ
ファイル・DB間の繋がり
参考程度ですが、 ファイル・DB間は以下のような繋がりとなっています。(一部のファイルは省略しています)
今回のgemを作ってみて...
肌感ではありますが、意図せぬケアレスミスは相当減らせたのではないかと思っています。何より楽しいのでモチベーションUPにも繋がり内向き・外向きの課題も解決することができました。また、今回は偶然課題を発見できたので工夫して取り組むことができたのですが、発見までのプロセスをもっと再現性のあるものにしたいです。課題を解決するまでの過程はGoogleで調べたり社員の方に聞いたりすると大体の方針は立てられて解決に向かってトライアンドエラーを繰り返すだけなのでやるべきことはシンプルです。しかし、今の僕の場合課題発見までの過程はやるべきことが決まっておらず偶発的なものが多いです。普段行っているタスクやみんなの呟きから見つけられる問題は沢山あるはずなので、どのように見つけるのかを日々考え日常の習慣となるようにしていきたいです。
今後の課題
gemとして作ったからには皆さんにも使って頂きたいので、今後も改善していきます。使ってみて感じている課題は以下の通りです。
- テーブルが多い時めっちゃ見にくい
- validationを作りたいモデルファイルがいくつもある場合何回も走らせなければならない
- モデルファイルを直接書き換えるのはやはり怖い
名前の由来(小ネタ)
今回gemを実装する上でpretty_validationを非常に参考にさせて頂きました。その敬意を込めspicy_validationという名前にしました。
マネーフォワードでは、エンジニアを募集しています。 ご応募お待ちしています。
【サイトのご案内】 ■マネーフォワード採用サイト ■Wantedly ■京都開発拠点
【プロダクトのご紹介】 ■お金の見える化サービス 『マネーフォワード ME』 iPhone,iPad Android
■ビジネス向けバックオフィス向け業務効率化ソリューション 『マネーフォワード クラウド』
■だれでも貯まって増える お金の体質改善サービス 『マネーフォワード おかねせんせい』