LoginSignup
71
48

More than 5 years have passed since last update.

Railsでネームスペース付きのモデルでテーブル名にプレフィックスをつける

Last updated at Posted at 2016-02-08

タイトルの通りですが、具体的には以下のコマンドでモデルをgenerateしてあげれば、実現できます。
Admin::User というモデルで admin_users というテーブルを作りたい場合、以下のコマンドで作成できます。

bundle exec rails g model Admin::User email password flag

実行結果としてこれらのファイルが生成されます
      invoke  active_record
      create    db/migrate/20160202020202_create_admin_users.rb
      create    app/models/admin/user.rb
      create    app/models/admin.rb
      invoke    rspec
      create      spec/models/admin/user_spec.rb
app/models/admin.rb
module Admin
  def self.table_name_prefix
    'admin_'  #<= DBのtable名にadmin_というプレフィックスがあることが前提
  end
end
app/models/admin/user.rb
class Admin::User < ActiveRecord::Base
end

app/models/admin.rbtable_name_prefix というクラスメソッドをオーバーライドしています。

Railsではなぜかネームスペースとなる親のModuleに定義してあげると table_name_prefix が有効な状態となります。
ネームスペースとなっているModuleにメソッドを定義するだけで、そのメソッドが実行できるわけではないので気になって詳しく調べてみました。
通常Rubyだと self.hoge などで始まる 特異メソッドextend しないとダメです。

以下のActiveRecordのソースにコメントで書かれていました。

activerecord/lib/active_record/model_schema.rb#L25-L27
      # If you are organising your models within modules you can add a prefix to the models within
      # a namespace by defining a singleton method in the parent module called table_name_prefix which
      # returns your chosen prefix.

意訳すると以下の感じでしょうか。

まとめたい(organisingしたい)ときはネームスペース(parent)となっている Admin のモジュールに定義することで可能。

実装コードは以下。parents で親のモジュールに table_name_prefix の定義があるかを判定しあれば返すという実装になっていました。

activerecord/lib/active_record/model_schema.rb#L151-L153
      def full_table_name_prefix #:nodoc:
        (parents.detect{ |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
      end
71
48
2

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
71
48