Webフレームワークの新しい波 Waves探訪記

第5回 Twのユーザにフォローする/されるの関係を導入する

この記事を読むのに必要な時間:およそ 3 分

Twitter風のフォローする/されるの考え方

これまで作ってきたTwitter風シンプルアプリTwは,参加者全員の発言を全ての参加者の画面に表示していました。しかし実際のTwitterでは,画面に表示されるのは,自分の発言と,自分が「フォロー」している参加者の発言だけです。「フォロー」とは「この参加者の発言を読む」と決めることです。注意すべきなのは,フォローした参加者の発言は読めるようになりますが,「フォローされる」側ではそうはならないということです。お互いの発言が読めるようになるには,お互いが明示的にフォローする必要があります。

この参加者同士の関係をTwでも組み込んでみましょう。

関連(association)

Twでは一人のユーザが複数の発言を行います。したがってUserモデルには次の宣言がありました。

Userモデルに設定した関連

one_to_many :words, :class=>Tw::Models::Word

これを「関連」と呼びます。Wordモデルには,これと逆の関連(many_to_one)が宣言されています。Ruby on RailsのActiveRecoredにもまったく同様の機能があり,Railsユーザになじみやすいように,Waves(のORパーであるSequel)ではbelongs_toやhas_manyといったメソッド名が使えるようになっています。

WavesのO/RマッパーであるSequelのサポートする関連には次の3種類があります。

  • one_to_many : 一対多
  • mant_to_one : 多対一
  • many_to_many : 多対多

フォローを関連に置き換える

Twitterのフォローは「あるユーザが別のユーザをフォローしている」という関連です。一人のユーザは何人のユーザでもフォローすることができますし,何人のユーザにフォローされることも可能です。つまりフォローする/されるは多対多の関連になります。

関連は異なるテーブル間で宣言されるケースが多いのですが,フォローでは「ユーザがユーザをフォローする/される」なので,自分自身に対して関連を宣言する必要があります。これを自己参照型多対多の関連と呼ぶことがあります。

交差テーブル(join table)

多対多の関連を作るには,関連する2つの(自己参照のときは1つの)テーブルの他に,交差テーブル(join table)と呼ばれるものが必要になります。交差テーブルは関連する2つのモデルのidの対応表です。今回はUserテーブル同士の対応をとるので,ユーザのidを別のユーザのidに対応付けるテーブルになります。

ActiveRecoredでは交差テーブルはidカラムを持ってはならないなどの制約がありますが,Sequelでは特に無いようです。

フォローする/されるの実装

交差テーブルを作る

交差テーブルを作るためにマイグレーションファイルを生成します。

交差テーブルのマイグレーション用のファイルを作る

rake schema:migration name=add_join_table

schema/migrations/003_add_join_table.rb(ファイル名先頭の数値はマイグレーションをファイルを作った回数に応じて変化するので003とは限りません)が生成されますので,以下のように修正します。

交差テーブルのマイグレーション用のファイル

class AddJoinTable < Sequel::Migration

  def up
    create_table :followed_following do
      foreign_key :followed_id, :table=>:users
      foreign_key :following_id, :table=>:users
    end
  end
  
  def down
    drop_table :followed_following
  end

end

交差テーブルの名前はfollowed_followingです。2つのカラムfollowed_idとfollowing_idを持ち,それぞれUserテーブルを参照しています。

次にこの交差テーブルを使って多対多を実装します。models/user.rbを以下のように修正してください。

自己参照型多対多の設定

module Tw
  
  module Models
    
    class User < Sequel::Model(:users)

      many_to_many :followed_users,
          :class=>Tw::Models::User,
          :join_table=>:followed_following,
          :left_key=>:following_id,
          :right_key=>:followed_id
         
      many_to_many :following_users,
          :class=>Tw::Models::User,
          :join_table=>:followed_following,
          :left_key=>:followed_id,
          :right_key=>:following_id
          
      one_to_many :words, :class=>Tw::Models::Word
      
      after_create do
        set(:created_on => Time.now) if columns.include? :created_on
      end
      
      before_save do
        set(:updated_on => Time.now) if columns.include? :updated_on
      end
      
    end
    
  end
  
end

many_to_manyを宣言するわけですが,いくつかのパラメータ設定が必要になります。

関連の名前

many_to_manyの最初のパラメータ「:followed_users」は,その関連の名前です。Rubyのコードからはこの名前でアクセスできるにようになります。その後ろにはHash型のパラメータになります。

classパラメータ

この関連が参照している対象のモデルのクラス名を宣言します。省略した場合には,関連の名前を使います。

join_tableパラメータ

交差テーブルの名前をシンボルで指定します。省略した場合には,関連付けられる2つのモデル名を複数形にしてアルファベット順に並べアンダースコアで接続した名前になります。

left_key,right_keyパラメータ

left_keyは,交差テーブルで自分をさす外部参照カラムの名前をシンボルにしたもの。right_keyは,交差テーブルで相手をさす外部参照カラムの名前をシンボルにしたものになります。

その他のパラメータ

selectパラメータにセレクトする対象のカラム名(属性名)を指定できます。デフォルトは「自分のテーブルの全カラム」で,交差テーブルの属性は取得できません。交差テーブルにid以外の情報を持たせたいときは(例えば生成時刻),ここに指定すれば取得できるようになります。

マイグレートする

マイグレーション用のファイルからデータベースを設定する

rake schema:migrate

これで新しい交差テーブルができます。

著者プロフィール

松永肇一(まつながけいいち)

株式会社ライフメディア 創造推進部プロジェクトマネージャ。東京都出身。千葉大学工学部での卒論テーマは人工知能関連だったが,富士通に入社後はPCのソフトウェア開発に関わる。"GNU for Towns"のために,リチャード・ストールマンに会いにいくような妙な仕事を経て現職。Ruby on Railsを使ってWebアプリを開発する毎日。ブログは「ma2の日記」。

URLhttp://d.hatena.ne.jp/ma2/

コメント

コメントの記入