[前][次][番号順一覧][スレッド一覧]

rails:2240

From: "Information Kanasansoft" <kanasansoft@g...>
Date: Fri, 22 Jun 2007 20:35:27 +0900
Subject: [rails:2240] 履歴を考慮した多対多のアソシエーション

kanasanです。
初めて質問します。

現在、多対多のアソシエーションを持つ
DBの設計を行っています。
結合テーブル(ブリッジテーブル)を
使用しようとしているのですが
次の問題が発生し行き詰ってしまいました。

当システムはデータウェアハウス的な
利用を想定している為、
全データに対して履歴を持たなくてはなりません。
しかし、RoRを利用しつつ
ブリッジテーブルを使用しながら
履歴を管理する方法を
見つけ出すことができませんでした。

以下、(大学の)クラブと学生を例にします。
(業務上の理由で
実例を挙げられないことをお断りします。
例は全てML投稿用に書き下ろしました。)

履歴を残さないのであれば
次のsqlとコードで十分です。

ここから========================================
ER図
  club
  ┃[n]
  ┃[1]
  club_student
  ┃[1]
  ┃[n]
  student
----------------------------------------
SQL
create table clubs (
  id                int             not null auto_increment,
  name              varchar(255)    not null,
  ...(略)...
  primary key (id)
);
create table students (
  id                int             not null auto_increment,
  name              varchar(255)    not null,
  ...(略)...
  primary key (id)
);
create table clubs_students (
  club_id           int             not null,
  student_id        int             not null,
  ...(略)...
  constraint fk_club
    foreign key (club_id)    references clubs(id),
  constraint fk_student
    foreign key (student_id) references students(id),
  primary key (club_id, student_id)
);
----------------------------------------
RoR
class Club < ActiveRecode::Base
  has_and_belongs_to_many :students
  ...(略)...
end
class Student < ActiveRecode::Base
  has_and_belongs_to_many :clubs
  ...(略)...
end
ここまで========================================

上記の構造に履歴機能を持たせる為に
次のように変更しました。
  ・各テーブルが履歴を持てるように
   全ての情報を表出しし
   テーブル「〜_information」として定義
  ・テーブル「〜_information」と元テーブルをFKで接続
  ・履歴の有効期限(範囲)を管理する為に
   作成日時・削除日時カラムを追加
  ・テーブルにあわせクラス「〜_information」を定義
  ・クラス「〜_information」と
   元のクラスのアソシエーションの宣言を追加

ここから========================================
ER図
  club_information
  ┃[n]
  ┃[1]
  club
  ┃[n]
  ┃[1]
  ┃     [1][n]
  club_student━━━club_student_information
  ┃[1]
  ┃[n]
  student
  ┃[1]
  ┃[n]
  student_information
----------------------------------------
SQL
create table clubs (
  id                int             not null auto_increment,
  primary key (id)
);
create table club_information (
  id                int             not null auto_increment,
  club_id           int             not null,
  name              varchar(255)    not null,
  ...(略)...
  create_at         datetime        null,
  delete_at         datetime        null,
  constraint fk_club_information
    foreign key (club_id)    references clubs(id),
  primary key (id)
);
create table students (
  id                int             not null auto_increment,
  primary key (id)
);
create table student_information (
  id                int             not null auto_increment,
  student_id        int             not null,
  name              varchar(255)    not null,
  ...(略)...
  create_at         datetime        null,
  delete_at         datetime        null,
  constraint fk_student_information
    foreign key (student_id) references students(id),
  primary key (id)
);
create table clubs_students (
  id                int             not null auto_increment,
  club_id           int             not null,
  student_id        int             not null,
  constraint fk_club
    foreign key (club_id)    references clubs(id),
  constraint fk_student
    foreign key (student_id) references students(id),
  primary key (club_id, student_id)
);
create table clubs_students_information (
  id                int             not null auto_increment,
  clubs_students_id int             not null,
  ...(略)...
  create_at         datetime        null,
  delete_at         datetime        null,
  constraint fk_club_student_information
    foreign key (clubs_students_id)    references clubs_students(id),
  primary key (id)
);
----------------------------------------
RoR
class Club < ActiveRecode::Base
  has_and_belongs_to_many :students
  has_many :club_information
  ...(略)...
end
class ClubInformation < ActiveRecode::Base
  belongs_to :club
  ...(略)...
end
class Student < ActiveRecode::Base
  has_and_belongs_to_many :clubs
  has_many :student_information
  ...(略)...
end
class StudentInformation < ActiveRecode::Base
  belongs_to :student
  ...(略)...
end
class ClubsStudents < ActiveRecode::Base
  has_many :club_student_information
  ...(略)...
end
class ClubsStudentsInformation < ActiveRecode::Base
  belongs_to :club_student
  ...(略)...
end
ここまで========================================

この変更により次の問題が発生します。
  ・全てのデータが物理削除ではなく論理削除になるため
   例外を除きSQLがinsertのみとなり
   RoRでせっかく準備されているメソッドが
   使えなくなる(or 使いづらくなる)
   (例外は削除日時のupdateのみ)
  ・テーブル「clubs_students_information」の
   カラム「clubs_students_id」が
   RoRの単複数形の規約に則れない
  ・クラス「ClubsStudents」・クラス「ClubsStudentsInformation」も
   RoRの単複数形の規約に則れない
等、他にも色々と問題が発生そうです。

このような場合、定石のようなモデルがあるのでしょうか。
それとも、RoRには私の知らない宣言が準備されているのでしょうか。
良いアイディアをお持ちの方や
このような状況を経験された方はいらっしゃいませんでしょうか。

宜しくお願いします。

--
ML: rails@r...
使い方: http://QuickML.com/

[前][次][番号順一覧][スレッド一覧]

->    2240 2007-06-22 13:35 [kanasansoft@g...    ] 履歴を考慮した多対多のアソシエーション  
      2241 2007-06-22 17:27 ┗[sudo@w...           ]                                       
      2244 2007-06-23 18:04  ┗[kanasansoft@g...    ]                                     
      2247 2007-06-25 08:31   ┗[yamajaki@g...       ]                                   
      2248 2007-06-26 03:36    ┗[kanasansoft@g...    ]