Railsと複合主キー その2
なかなか時間が取れないけど、ちょっとだけ複合主キー(CPK)*1テーブルのマイグレーションとアクセスを試してみた。ちゃんとしたパターンテストはしていないが…
これは結構イケてる!
マイグレーション
こんな感じ*2
class CreatePermissions < ActiveRecord::Migration def self.up create_table :permission, :primary_key => [:role_cd, :action_cd] do |t| t.column :role_cd, :string, :limit => 20 t.column :action_cd, :string, :limit => 20 t.column :is_permitted, :boolean t.column :updated_at, :timestamp end end def self.down drop_table :permission end end
このprimary_key指定が、idでない単一キーの時に使えるといいのだが、そうは問屋が卸さない。参考にさせていただいた2006-10-25にもあるが、primary_key指定は、暗黙に「自動採番のInteger型」に定義されているのだった。
アクセス
consoleで試したら、こんなことが出来る。
>> p = Permission.new => #<Permission:0xb72c2f38 @attributes={"updated_at"=>nil, "action_cd"=>nil, "is_permitted"=>nil, "role_cd"=>nil}, @new_record=true> >> p.role = Role.find(:first) => #<Role:0xb72bee38 @attributes={"updated_at"=>"2007-09-13 22:32:15.328273", "role_name"=>"部門アシスタント", "role_cd"=>"DA"}> >> p.action = Action.find('show_news') => #<Action:0xb72ba464 @attributes={"updated_at"=>"2007-09-13 23:59:55.983605", "action_name"=>"Show Whats New", "action_cd"=>"show_news", "module_name"=>"Menu"}> >> p.save => true >> p2 = Action.find('show_news').permissions[0] => #<Permission:0xb72a14dc @attributes={"updated_at"=>"2007-09-14 00:02:26.987196", "action_cd"=>"show_news", "is_permitted"=>nil, "role_cd"=>"DA"}> >> p2.role => #<Role:0xb729e714 @attributes={"updated_at"=>"2007-09-13 22:32:15.328273", "role_name"=>"部門アシスタント", "role_cd"=>"DA"}> >> Permission.find(['DA', 'show_news']) => #<Permission:0xb729a0b0 @attributes={"updated_at"=>"2007-09-14 00:02:26.987196", "action_cd"=>"show_news", "is_permitted"=>nil, "role_cd"=>"DA"}>
面白ーい。varcharの複合主キーは、ちゃんと使えている。最後の複合主キーのfindはちょっとぎごちない感じがするけど、もっと上手い書き方があるのかも知れない*3。
ちなみにモデル定義は
class Role < ActiveRecord::Base set_primary_key :role_cd has_many :permissions, :foreign_key => :role_cd end class Action < ActiveRecord::Base set_primary_key :action_cd has_many :permissions, :foreign_key => 'action_cd' end class Permission < ActiveRecord::Base set_primary_keys :role_cd, :action_cd belongs_to :role, :foreign_key => :role_cd belongs_to :action, :foreign_key => :action_cd end
いい感じなので、ちゃんと検証する気になった。
(つづく)
*1:http://compositekeys.rubyforge.org/
*2:レガシー調を出すため、単数系のテーブル名、マスター側の主キーは"id"ではなくStringの「xxコード」にしてみた
*3:HashにしたらNGだった。キーの順番覚えてないとダメかなぁ?