rails 學(xué)習(xí)筆記


layout: post
title: 第十一章困惑 外鍵 及 反轉(zhuǎn)relationships表
categories:

  • rails
    tags:
  • railstutorail 學(xué)習(xí)筆記

不知道有誰學(xué)到11章時和我一樣困惑的累贤,所謂的對調(diào)兩列的位置钞翔,組建成reverse_ralationships表究竟是什么意思。畢竟表根本沒變就是原來那個表阿笤虫,已經(jīng)完整的體現(xiàn)了用戶間關(guān)系。誰是關(guān)注誰是被關(guān)注根本沒變先蒋,追人的沒突然變成被追啊隅津,攜帶信息完全一樣。

沒錯稚机,真相就是:其實表就是原來的表,根本沒變获搏。表沒有反轉(zhuǎn)赖条,反轉(zhuǎn)的是外鍵,從而反轉(zhuǎn)查詢方向常熙。因為Users表和relationships表通過外鍵一一對應(yīng)纬乍,所以把表重命是為了另設(shè)外鍵。根本就沒有任何將表進行反轉(zhuǎn)的處理裸卫。仿贬。你把User.rb中的reverse_relationships 都改成 same_relationships 試試,結(jié)果一樣墓贿。取名reverse, 其實是外鍵和查詢方向的reverse茧泪。

先說外鍵

第十章的user.microposts比較簡單, 生成micropost時無須指定外鍵,因為micopost 模型中就是user_id聋袋,只要正確定義了用戶和微博之間的關(guān)聯(lián)關(guān)系(has_many,belongs_to),使用user.microposts.build創(chuàng)建新微薄時队伟,rails 會自動將micropost中的user_id賦值為相應(yīng)的user.id。

運行驗證一下幽勒,rails console --sandbox:
1.9.3-p429 :001 > User.first.microposts.build
會新建一個micropost嗜侮,micropost的user_id屬性 自動賦值為 user.id (此例為User.first.id, "1"),其他屬性為nil,待給參數(shù)
User Load (0.5ms) SELECT "users".* FROM "users" LIMIT 1
=> #<Micropost id: nil, content: nil, user_id: 1, created_at: nil, updated_at: nil>

而relationship表中沒有叫user_id 的,只有對應(yīng)User的follower_id和followed_id,所以User表必須通過指定的外鍵和relationship表一一對應(yīng)锈颗。

書中先指定的外鍵是follower_id(你完全可以先指定followed_id)缠借,那么使用 user.relationships.build(followed_id: ...)建立relationship時,被設(shè)為外鍵的follower_id 會被自動賦對應(yīng)的 user.id值宜猜,而followed_id是你給的參數(shù),從而得到relationship表中的一行具體的relationship


1.9.3-p429 :002 > User.first.relationships
會列出 User.first 的所有的 follower_id =1的 relationships表
User Load (0.4ms) SELECT "users".* FROM "users" LIMIT 1
Relationship Load (46.7ms) SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = 1
=> [#<Relationship id: 21, follower_id: 1, followed_id: 2, created_at: "2013-07-21 13:52:10", updated_at: "2013-07-21 13:52:10">]


1.9.3-p429 :003 > User.first.relationships.build
會新建一個relationship, 其中follower_id 是User指定的外鍵硝逢,被賦值User.first.id,而followed_id則是nil,待給參數(shù)
User Load (0.4ms) SELECT "users".* FROM "users" LIMIT 1
=> #<Relationship id: nil, follower_id: 1, followed_id: nil, created_at: nil, updated_at: nil>


1.9.3-p429 :004 > User.first.relationships.build(followed_id: 2)
(想讓用戶1關(guān)注用戶2姨拥,傳入?yún)?shù)。注意沒save,relationship_id 為nil渠鸽。要save 用 User.first.relationships.create!(followed_id: 2))叫乌。
User Load (0.4ms) SELECT "users".* FROM "users" LIMIT 1
=> #<Relationship id: nil, follower_id: 1, followed_id: 2, created_at: nil, updated_at: nil>

relationship表建立后,就可以通過
has_many:followeds,through: :relationships
使用followed_id 生成 user.followeds 數(shù)組徽缚。為了好聽憨奸,書中用
has_many:followed_users, through: :relationships, source: :followed 把user.followeds改成了 user.followed_users

user.followed_users 通過relationships表將 follower_id =(user.id) 所有對應(yīng)的 followed_id 從數(shù)據(jù)庫中找出生成數(shù)組。即該user的“關(guān)注的人”列表凿试。
(例如下面我找User.first所有關(guān)注的人排宰,即查詢follower_id = 1 對應(yīng)的 followed_id)

運行rails console --sandbox:
1.9.3-p429 :005 > User.first.followed_users
得到了User.first 的所有關(guān)注的人(我這只有一個,User.id=2的, 說明User1 只關(guān)注了 User2)那婉。
User Load (0.4ms) SELECT "users".* FROM "users" LIMIT 1
User Load (0.4ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = 1
=> [#<User id: 2, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2013-07-21 10:50:11", updated_at: "2013-07-21 10:50:11", password_digest: "$2a$.....", remember_token: "9c2eccc....."]


困惑的revese_relationships表

上面說明了指定了follower_id為外鍵的情況

所以User.rb模型中這兩句的意思就是

has_many :relationships,foreign_key:"follower_id",dependent: :destroy
對于relationships表板甘,User_id固定對應(yīng)follower_id,所以使用user.relationships得到的是所有 follower_id值為user_id的 relationship數(shù)組
has_many :followed_users, through: :relationships, source: :followed
通過表查詢對應(yīng)的followed_id擁有了很多followed_users详炬。所以使用user.followed_users可得到該user的followed_users數(shù)組盐类,即在追哪些人。

下面說怎么通過關(guān)系表(再次強調(diào)呛谜,就是一張表) 查找出該user所有的“粉絲”列表在跳。

通過調(diào)換 followed_id為外鍵(所以通過表查詢的方向就反過來了,現(xiàn)在固定的是followed_id隐岛,來查詢表中對應(yīng)的follower_id數(shù)組猫妙。(比如對于user2, user.followers則通過relationships表 將 followed_id =2 對應(yīng)的所有 follower_id 找出來,即user2的粉絲數(shù)組)

所以User.rb模型中這兩句的意思就是

has_many :same_relationships, foreign_key: "followed_id",class_name: "Relationship",dependent: :destroy
對于same_relationships表(呵呵礼仗,不用reverse試試),User_id固定對應(yīng)于followed_id,所以使用user.same_relationships得到的是所有 followed_id值為user_id的 relationship數(shù)組
has_many :followers, through: :same_relationships, source: :follower
通過表查詢對應(yīng)的follower_id擁有了很多followers.所以使用user.followers可得到該user的followers數(shù)組吐咳,即粉絲團)

外鍵和表一一對應(yīng),所以表得改名,否則查詢關(guān)系就沖突了元践,user.relationships 不知道user_id賦值給誰查詢韭脊。)


(其實認真的看看下面4句中的SELECT語句就明白了,全是通過relationship表单旁,變的只是查詢的外鍵值)

1.9.3-p429 :006 > user2 = User.find(2)
1.9.3-p429 :007 > user2.relationships Relationship Load (0.2ms) SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = 2 => [#<Relationship id: 24, follower_id: 2, followed_id: 1, created_at: "2013-07-29 13:29:56", updated_at: "2013-07-29 13:29:56">]


1.9.3-p429 :008 > user2.same_relationships
Relationship Load (30.8ms) SELECT "relationships".* FROM "relationships" WHERE "relationships"."followed_id" = 2
=> [#<Relationship id: 21, follower_id: 1, followed_id: 2, created_at: "2013-07-21 13:52:10", updated_at: "2013-07-21 13:52:10">]


1.9.3-p429 :009 > user2.followers User Load (0.3ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = 2 => [#<User id: 1, name: "lafmad", email: "inaircastle@gmail.com", created_at: "2013-07-16 14:01:47", updated_at: "2013-07-20 03:14:16", password_digest: "$2a$10$....", remember_token: "tRLqtITZxX..."]


1.9.3-p429 :010 > user2.followed_users User Load (0.5ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = 2 => [#<User id: 1, name: "lafmad", email: "inaircastle@gmail.com", created_at: "2013-07-16 14:01:47", updated_at: "2013-07-20 03:14:16", password_digest: "$2a$10$m5bBDpsDXDv......", remember_token: "tRLqtIT..."]


寫完了我是更明白了沪羔,如果有讀者的話,希望沒把你搞的更糊涂。沉住氣蔫饰,忽然間一回頭就明白了(然后又糊涂了琅豆,然后又明白了,嗯嗯篓吁。)


以上


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末茫因,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子杖剪,更是在濱河造成了極大的恐慌冻押,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盛嘿,死亡現(xiàn)場離奇詭異洛巢,居然都是意外死亡,警方通過查閱死者的電腦和手機次兆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門稿茉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人芥炭,你說我怎么就攤上這事漓库。” “怎么了园蝠?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵米苹,是天一觀的道長。 經(jīng)常有香客問我砰琢,道長蘸嘶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任陪汽,我火速辦了婚禮训唱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挚冤。我一直安慰自己况增,他們只是感情好,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布训挡。 她就那樣靜靜地躺著澳骤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪澜薄。 梳的紋絲不亂的頭發(fā)上为肮,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天,我揣著相機與錄音肤京,去河邊找鬼颊艳。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的棋枕。 我是一名探鬼主播白修,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼重斑!你這毒婦竟也來了兵睛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤窥浪,失蹤者是張志新(化名)和其女友劉穎卤恳,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寒矿,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年若债,在試婚紗的時候發(fā)現(xiàn)自己被綠了符相。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡蠢琳,死狀恐怖啊终,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情傲须,我是刑警寧澤蓝牲,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站泰讽,受9級特大地震影響例衍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜已卸,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一佛玄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧累澡,春花似錦梦抢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蕊梧,卻和暖如春霞赫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肥矢。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工绩脆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓靴迫,卻偏偏與公主長得像惕味,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子玉锌,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容