あるモデルのサブクラスを定義する
サブクラスの作成等を、 Rails が受け持ってくれる機能について。ファイルのアップロードなど、場合によって validation の条件を分けたりしたい時などにも便利です。
前提
Rails の機能で簡単にサブクラスを作成する場合、親クラスに type というカラムを string 型で定義します。
# RAILS_ROOT/bd/migrate/XXX_create_users.rb class CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.string :login t.string :password t.string :type t.timestamps end end def self.down drop_table :users end end
これだけで、サブクラスの実装を Rails 側で自動的に行ってくれます。
サブクラスの定義
サブクラスの定義は、通常の Ruby の文法で行います。
# RAILS_ROOT/app/models/user.rb class User < ActiveRecord::Base end
# RAILS_ROOT/app/models/super_user.rb class SuperUser < User end
これで SuperUser が User のサブクラスになりました。
使用方法
上のように定義しておくと、 find などを用いる際にサブクラスを指定する事で、自動的にサブクラスのみから検索を行うよう Rails が処理してくれます。
# すべてのスーパーユーザを検索する @super_users = SuperUser.find(:all) # すべてのユーザを検索する @users = User.find(:all) # スーパーユーザを新規作成(type カラムに "SuperUser" が自動入力される) @new_super_user = SuperUser.new # ユーザを新規作成(type カラムは設定されない) @new_user = User.new
コードにも書きましたが、親クラスを new した場合 type カラムには値が代入されないので注意して下さい。
また、サブクラス間でインスタンスを直接代入する事もできません。
# RAILS_ROOT/app/models/another_user.rb class AnotherUser < User end
@another_user = AnotherUser.find(params[:id]) # これはエラーになる @super_user = SuperUser.new(@another_user)
このような場合、一つ一つの値を代入していくのは馬鹿らしいので、手動で type に値を代入する方法などが考えられます。
# User として find してくる @another_user = User.find(params[:id]) # こちらも User として新規作成して @super_user = User.new(@another_user) # type を設定してしまう @super_user.update_attribute(:type, "SuperUser")