2011-04-03 33 views
2
create_table "friendships", :force => true do |t| 
    t.integer "user_id" 
    t.integer "friend_id" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "likes", :force => true do |t| 
    t.string "name" 
    t.integer "user_id" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

    create_table "users", :force => true do |t| 
    t.string "name" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    end 

這些都是:has_many:通過不與會議名稱關聯?

class User < ActiveRecord::Base 

    has_many :friendships 
    has_many :friends, :through => :friendships 
    has_many :likes 
    has_many :friends_likes, :through => :friendships, :source => :likes 

end 

class Friendship < ActiveRecord::Base 

    belongs_to :user 
    belongs_to :friend, :class_name => "User", :foreign_key => "friend_id" 
    has_many :likes, :foreign_key => :user_id, 
end 

class Like < ActiveRecord::Base 

    belongs_to :user 
    belongs_to :friendship 

end 

我試圖讓「朋友喜歡」的模型,但我不能。

「User.find(1).friends_likes」 給出了SQL查詢

SELECT "likes".* FROM "likes" INNER JOIN "friendships" ON "likes".user_id = "friendships".id WHERE (("friendships".user_id = 1)) 

但我認爲必須是「INNER JOIN 「友誼」 ON 「喜歡」 .user_id = 「友誼」。friend_id

我該怎麼做? 感謝

回答

1

最簡單的解決方案可能是在User模型,構建正確的SQL添加實例方法friends_likes

def likes_of_friends 
    friends.includes(:likes).map(&:likes) 
    end 

.includes(:likes)是性能,以避免N + 1查詢的情況。

然後你User.find(1).friends_likes將產生如下疑問,假設用戶1與IDS 2和3的朋友:

User Load (0.1ms) SELECT `users`.* FROM `users` LIMIT 1 
    User Load (0.4ms) SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.friend_id WHERE ((`friendships`.user_id = 1)) 
    Like Load (0.2ms) SELECT `likes`.* FROM `likes` WHERE (`likes`.user_id IN (2,3)) 

如果你真的需要在一個查詢中的一切,你可以寫直線上升的SQL:

Like.find_by_sql("select likes.* from 
    likes 
    inner join users as friends 
     on friends.id = likes.user_id 
    inner join friendships 
     on friendships.friend_id = friends.id 
    where friendships.users_id = 1; 
") 

不直截了當的原因是因爲一個用戶「擁有」了友誼 - 這是單向的,而且似乎沒有辦法獲得與「朋友」相關的友誼(指定通過友誼桌上的friend_id E)。

所以,並稱相反的方向將有助於(奇怪的命名除外):

class Friendships 
    # ... 
    has_many :befriendedships, :class_name => "Friendship", :foreign_key => "friend_id" 
end 

然後,您可以查詢你更簡單地找了一下的東西:

Like.joins(:user => :befriendedships).where(["friendships.user_id = ?", 1]) 

這將生成與find_by_sql示例基本相同的SQL。