TodoList: join を使って todo/list を制限2006年12月26日 09時51分51秒

さて、todo/list に所属団体 (Organization) に応じた制限を掛けたい。今回は list.rhtml 用のクエリを作る。個人的にデータベースを真剣に使う機会はほとんどなかったので、試行錯誤が少々必要だった。

まずは、大元となるテーブルの内容だ。


mysql> select * from todo_organization_permissions;
+----+---------+-----------------+-----------+
| id | todo_id | organization_id | published |
+----+---------+-----------------+-----------+
|  1 |       1 |               1 |         1 | 
|  2 |       1 |               2 |         1 | 
|  3 |       1 |               4 |         0 | 
|  4 |       2 |               1 |         1 | 
|  5 |       1 |               3 |         1 | 
+----+---------+-----------------+-----------+
5 rows in set (0.00 sec)

このテーブルに対し、organization_id の一致するレコードを検索し、その中から、published が 1 のレコードに絞り込めば良い。上記のテーブルだと id が 1 と 4 のレコードだ。つまり todo_id が 1 と 2 のレコードを todos テーブルから取ってくればいいことになる。

join を使えば出来るのはすぐにわかった。join で結合したいクエリを、まずは試した後に join を実際に使ったクエリを書くと簡単に出来る。


mysql> select * from todo_organization_permissions where organization_id = 1;
+----+---------+-----------------+-----------+
| id | todo_id | organization_id | published |
+----+---------+-----------------+-----------+
|  1 |       1 |               1 |         1 | 
|  4 |       2 |               1 |         1 | 
+----+---------+-----------------+-----------+
2 rows in set (0.00 sec)

そして、その結果を元に、todos からレコードを引き出す。


mysql> select * from todos
 inner join todo_organization_permissions on todo_organization_permissions.todo_id = todos.id
 where published = 1 AND organization_id = 1;
+----+------------------+------+----+---------+-----------------+-----------+
| id | description      | done | id | todo_id | organization_id | published |
+----+------------------+------+----+---------+-----------------+-----------+
|  1 | create todo list |    0 |  1 |       1 |               1 |         1 | 
|  2 | enter todos      |    0 |  4 |       2 |               1 |         1 | 
+----+------------------+------+----+---------+-----------------+-----------+
2 rows in set (0.01 sec)

それを app/controllers/todo_controller.rb に find_all() に合う形で書き直せば良い。以下のコードには実験用のコードもまだ残っている。


  def list
    #@todo_pages, @todos = paginate(:todos, :per_page => 10)
    sql = "select * from todos inner join todo_organization_permissions " +
      " on todo_organization_permissions.todo_id = todos.id where " +
      "published = 1 AND organization_id = " + "1"
    #@todo_pages, @todos = paginate_by_sql(sql, 10) # doesn't exist by default
    @todo_pages, @todos = paginate(:todos,
      :joins => "LEFT JOIN todo_organization_permissions" +
      " on todo_organization_permissions.todo_id = todos.id where " +
      "published = 1 AND organization_id = " + "1",
      :per_page => 10)
  end

今回は、organization_id の取得の仕方が分からないので、"1" と直書きした。

前回次回

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://uyota.asablo.jp/blog/2006/12/26/1074577/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。