Twitter風のフォローする/されるの考え方
これまで作ってきたTwitter風シンプルアプリTwは、
この参加者同士の関係をTwでも組み込んでみましょう。
関連(association)
Twでは一人のユーザが複数の発言を行います。したがってUserモデルには次の宣言がありました。
one_to_many :words, :class=>Tw::Models::Word
これを
WavesのO/
- one_
to_ many : 一対多 - mant_
to_ one : 多対一 - many_
to_ many : 多対多
フォローを関連に置き換える
Twitterのフォローは
関連は異なるテーブル間で宣言されるケースが多いのですが、
交差テーブル(join table)
多対多の関連を作るには、
ActiveRecoredでは交差テーブルはidカラムを持ってはならないなどの制約がありますが、
フォローする/されるの実装
交差テーブルを作る
交差テーブルを作るためにマイグレーションファイルを生成します。
rake schema:migration name=add_join_table
schema/
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_
次にこの交差テーブルを使って多対多を実装します。models/
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_
関連の名前
many_
classパラメータ
この関連が参照している対象のモデルのクラス名を宣言します。省略した場合には、
join_tableパラメータ
交差テーブルの名前をシンボルで指定します。省略した場合には、
left_key、right_keyパラメータ
left_
その他のパラメータ
selectパラメータにセレクトする対象のカラム名
マイグレートする
rake schema:migrate
これで新しい交差テーブルができます。
コンソールで試してみる
これでUserモデルに以下のような新しいメソッドが追加されたはずです。
- followed_
users - 自分をフォローしているユーザを返すデータセット
(後述) - following_
users - 自分がフォローしているユーザを返すデータセット
(後述) - add_
followed_ user - パラメータのユーザを、
新たに自分をフォローするユーザに追加する - add_
following_ user - パラメータのユーザを、
新たに自分がフォローしているユーザに追加する - remove_
followed_ user - パラメータのユーザを、
自分をフォローするユーザから削除する - remove_
following_ user - パラメータのユーザを、
自分がフォローしているユーザから削除する
正しくフォローする/される関係が作れたか、
>> u1 = Tw::Models::User.find(:name=>'foo') => #<Tw::Models::User @values={:name=>"foo", :password=>"bar", :id=>2}> >> u2 = Tw::Models::User.find(:name=>'hoge') => #<Tw::Models::User @values={:name=>"hoge", :password=>"hoge", :id=>3}> >> u1.following_users => #<Sequel::SQLite::Dataset: "SELECT * FROM users INNER JOIN followed_following ON (followed_following.followed_id = 2) AND (fo llowed_following.following_id = users.id)"> >> u1.following_users.all => [] >> u1.add_following_user(u2) => #<Tw::Models::User @values={:name=>"hoge", :password=>"hoge", :id=>3}> >> u1.following_users.all => [#<Tw::Models::User @values={:following_id=>3, :followed_id=>2, :name=>"hoge", :password=>"hoge", :id=>3}>] >>
「u1 = Tw::Models::User.
「u1.
データセットとはRDBのビューのようなものです。対象となるデータを取得するための手続きで、
ここに実際にフォローするユーザを
ちょっとした問題
ここでもう一度
まとめと次回の予定
Twitterのメンバー間に存在するフォローする/されるという関係をTwでもまねてみました。Userモデル間に多対多の関連を設定することで、