パパエンジニアのアウトプット帳

30歳に突入した1児のパパエンジニアのブログ

dependent: :restrict_with_errorのI18n対応にちょっとつまずいた

dependent: :restrict_with_errorを利用した時に、エラーメッセージを日本語化しようとしてちょっと調べたのでメモとして残す。

ちなみに、dependentオプションについては下記がまとまってて分かりやすい。

qiita.com


例えば下記のようなモデルがあったとする。

class User < ActiveRecord::Base
  belongs_to :department
end

class Department < ActiveRecord::Base
  has_many :users, dependent: :restrict_with_error
end

restrict_with_errorのlocaleの書き方ははググればすぐ出てくるが、このrecordの部分が日本語にならなくて困った。。

[translation_ja.yml]
ja:
  activerecord:
    errors:
      messages:
        restrict_dependent_destroy:
          many: "%{record}が存在しているため削除できません。"

モデル名のI18nなので下記のように書けばいけると思っていたが、どうもusersと複数系になっているので違う(usersにもしてみたがダメ)

[translation_ja.yml]
  activerecord:
    models:
      user: "ユーザ"

コード見ていると下記のようになっている。

# File activerecord/lib/active_record/associations/has_many_association.rb, line 11
      def handle_dependency
        case options[:dependent]
        when :restrict_with_exception
          raise ActiveRecord::DeleteRestrictionError.new(reflection.name) unless empty?

        when :restrict_with_error
          unless empty?
            record = klass.human_attribute_name(reflection.name).downcase
            owner.errors.add(:base, :"restrict_dependent_destroy.many", record: record)
            false
          end

        else
          if options[:dependent] == :destroy
            # No point in executing the counter update since we're going to destroy the parent anyway
            load_target.each { |t| t.destroyed_by_association = reflection }
            destroy_all
          else
            delete_all
          end
        end
      end

whenのrestrict_with_error部分にklass.human_attribute_name(reflection.name).downcaseとある。

human_attribute_nameだと!?

なので下記のように対応したら日本語表示されました。

[translation_ja.yml]
  activerecord:
    attributes:
      user:
        users: ユーザ


なんか気持ち悪い。。。

RailsでのSI開発にRidgepoleは相性がいいのではないだろうか?

仕事でRailsでのSI開発を行っているのですが、毎回悩みの種の1つにDBのMigrationがあります。


SI開発の性質上、どうしても下記のドキュメントが必要であることが多いです。

  • テーブル定義書
  • ER図


仕事では、これらを作成するツールとして下記のA5:SQL Mk-2を利用しています。

A5:SQL Mk-2 - フリーの汎用SQL開発ツール/ER図ツール

このツールを使うことで、ER図を書くだけでテーブル定義書も出力できるのでとても便利です。

(テーブル定義書は必要に応じて加工することもありますが)


そして、このツールのさらに便利なところが、ER図からDDLを生成できるところです。

案件では開発の立ち上がりを早くするために、設計に利用したER図からDDL生成機能(ER図 > DDLを生成する)を利用してテーブル作成を行っているのですが、 開発初期はテーブル定義が変わることがよくあるので、この方法は重宝しています。


しかし、この方法だとRailsのMigration管理から外れているので、ある程度設計が落ち着いた段階でMigrationファイルを作成する作業が発生する。

(rake db:schema:dumpでschema.rbを生成してもいいですが、既存ではない新規のプロジェクトなのにそれをするのは気持ち悪いし、その後のカラム追加などをMigrationでやっていくのも・・・)

数テーブルなら大した労力ではないが、10を超えたあたりから面倒だしtypo等も発生する可能性がある。

そんな状況がどうにかならないものかと悶々としていたが、最近趣味のアプリで前々から使ってみようと思っていたridgepoleを使ってみて、そのあたりの問題が解決できそうだったのでまとめてみた。

(仕事ではまだ試せてないです)

Ridgepoleとは

簡単に言うと、スキーマ管理ツールです。

Railsマイグレーションと書き方が同じなので、難なく使えると思います。


詳しくはクックパッド様のブログやGithubをご覧ください。

techlife.cookpad.com

github.com

Ridgepoleを利用したMigrationの流れ

  1. A5:SQL Mk-2でER図を作成
  2. A5:SQL Mk-2のDDL生成機能でDDLを生成
  3. 生成されたDDLを実行
  4. ridgepoleでSchemafileをエクスポート
  5. ridgepole --applyでスキーマ作成(各開発者の環境)

その後は、SchemafileをGitなどで管理していく。

(コンフリクトが多発するのではと思われるが、自社の開発においてはスキーマを変更する人は限られるので問題ないと思っている。)

考察

この流れなら今までのツールを利用しつつ、途中でMigrationファイルをつくる手間も省ける!

(Migrationファイルがどんどん増えていくこともない!!)

capistranoなどを利用してデプロイを自動化しているのであれば、下記のようにしてrake db:migrateをridgepole用にしてもいいと思う。

(Deveseなどの導入でrake db:migrationが必要になることもあるので、alias_methodで別名タスクにしたらいいのではないかと思っている。)

walf443.hatenablog.com

追記(2016/07/16)

実際に試してみると、rakeファイル内でalias_methodが使えなかった。。。

どうしようかと調べていると古い記事だけど方法があったので、その方法を使ってる。

※rakeタスクをalias_method的なことする方法を知ってる方いたら教えてください!

metaskills.net

参考までに、こんなrakeファイルを作ってる。

gistc670a11fdebb35c6bac3bc2307576854


Deviseなどでmigrationがつくられる場合は、db:migrate:original → db:ridgepole:exportをする。

最後に

他にいい方法や、Railsでの開発でウチはこうしてる!みたいのがあれば教えてください。