SNSっぽい関連を実装してみる
- 各Userは0人以上の友達がいる
- 一方が友達リストに入れると、もう一方からも友達になる(現実には片想いってのもありますが、ここでは双方向ってことで。)
今回は、has_many :throughを使ってやってみました。
ちょっと付け加えれば関連にタグをつけたりも出来ると思います。
migration
class AuthenticatedUser < ActiveRecord::Migration def self.up # ユーザテーブル create_table :users do |t| t.column :userid, :string end add_index :users, :userid # コネテーブル create_table :connections do |t| t.column :from_id, :integer t.column :to_id, :integer end add_index :connections, :from_id add_index :connections, :to_id end def self.down drop_table :connections drop_table :users end end
user.rb
class User < ActiveRecord::Base has_many :connections, :foreign_key => 'from_id', :dependent => :destroy has_many :friends, :through => :connections, :source => :to validates_presence_of :userid validates_uniqueness_of :userid end
connection.rb
class Connection < ActiveRecord::Base belongs_to :from, :class_name => 'User', :foreign_key => 'from_id' belongs_to :to, :class_name => 'User', :foreign_key => 'to_id' # User.friendsへの操作で双方向のリンクを行えるように。 after_save :create_reverse_link after_destroy :destroy_reverse_link def create_reverse_link reverse_connection = Connection.find(:first, :conditions => [ "from_id = :to_id AND to_id = :from_id", { :to_id => self.to_id, :from_id => self.from_id } ]) if reverse_connection.nil? reverse_connection = Connection.new(:from_id => self.to_id, :to_id => self.from_id) raise "Create connection failure!" unless reverse_connection.save end end def destroy_reverse_link Connection.destroy_all("from_id = #{self.to_id} AND to_id = #{self.from_id}") end end