Rails 之旅第 2 天:Rails 關(guān)聯(lián)和拖動(dòng) div
大家好!今天是我搭建這個(gè)玩具項(xiàng)目的第 2 天。下面再來記錄一下關(guān)于 Rails 的一些有趣的事情吧!
目標(biāo):做一個(gè)冰箱詩歌論壇
我想做一種無聊的標(biāo)準(zhǔn)網(wǎng)站來學(xué)習(xí) Rails,并且其他人可以與之互動(dòng),就像一個(gè)論壇一樣! 但如果人們真的可以在網(wǎng)站上打字,那就會(huì)產(chǎn)生各種各樣的問題(如果他們是垃圾郵件發(fā)送者怎么辦?又或者只是言語刻???)。
我想到的第一個(gè)想法是,可以讓人們與網(wǎng)站互動(dòng),但實(shí)際上卻不能在網(wǎng)站上打字,那就是一個(gè)“冰箱詩歌論壇”,只給你一組固定的字,你就可以隨意組合。
所以,這就是我們的計(jì)劃!
我這個(gè)項(xiàng)目的目標(biāo)是想知道我是否能用 Rails 來做其他的小型網(wǎng)絡(luò)項(xiàng)目(而不是像我通常做的那樣,使用一些更基本的東西,比如 Flask,或者放棄后端,用 Javascript 來寫所有東西)。
怎么把字拖來拖去呢?jQuery 的可拖放 UI!
我想讓大家能夠把文字拖動(dòng)起來,但我又不想寫很多 Javascript。結(jié)果發(fā)現(xiàn)這超級(jí)簡(jiǎn)單 —— 有一個(gè) jQuery 庫可以做到,它叫做 draggable
!一開始,拖動(dòng)并不成功。
一開始拖動(dòng)在手機(jī)上是不行的,但是有一個(gè)技巧可以讓 jQuery UI 在手機(jī)上工作,叫做 jQuery UI touch punch。下面是它的樣子(有興趣看工作原理的可以查看源碼,代碼很少)。
banana
forest
cake
is
一個(gè)有趣的 Rails 功能:關(guān)聯(lián)
我以前從來沒有使用過關(guān)系型 ORM,對(duì)于 Rails,我很興奮的一件事就是想看看使用 Active Record 是什么樣子的!今天我了解了 Rails 的 ORM 功能之一:關(guān)聯(lián)。如果你像我一樣對(duì) ORM 完全不了解的話,那就來看看是怎么回事吧。
在我的論壇中,我有:
- 用戶
- 話題(我本來想把它叫做“線索”,但顯然這在 Rails 中是一個(gè)保留詞,所以現(xiàn)在叫做“話題”)。
- 帖子
當(dāng)顯示一個(gè)帖子時(shí),我需要顯示創(chuàng)建該帖子的用戶的用戶名。所以我想我可能需要寫一些代碼來加載帖子,并為每個(gè)帖子加載用戶,就像這樣(在 Rails 中,Post.where
和 User.find
將會(huì)運(yùn)行 SQL 語句,并將結(jié)果轉(zhuǎn)化為 Ruby 對(duì)象):
@posts = Post.where(topic_id: id)
@posts.each do |post|
user = User.find(post.user_id)
post.user = user
end
這還不夠好,它要為每個(gè)帖子做一次單獨(dú)的 SQL 查詢!我知道有一個(gè)更好的方法,我發(fā)現(xiàn)它叫做關(guān)聯(lián)。這個(gè)鏈接是來自 https://guides.rubyonrails.org 的指南,到目前為止,它對(duì)我很有幫助。
基本上我需要做的就是:
- 在
User
模型中添加一行has_many :post
。 - 在
Post
模型中添加一行belongs_to :user
。 - Rails 現(xiàn)在知道如何將這兩個(gè)表連接起來,盡管我沒有告訴它要連接到什么列上!我認(rèn)為這是因?yàn)槲野凑账谕膽T例命名了
posts
表中的user_id
列。 - 對(duì)
User
和Topic
做完全相同的事情(一個(gè)主題也有很多帖子:has_many :posts
)。
然后我加載每一個(gè)帖子和它的關(guān)聯(lián)用戶的代碼就變成了只有一行! 就是這一行:
@posts = @topic.posts.order(created_at: :asc).preload(:user)
比起只有一行更重要的是,它不是單獨(dú)做一個(gè)查詢來獲取每個(gè)帖子的用戶,而是在 1 個(gè)查詢中獲取所有用戶。顯然,在 Rails 中,有一堆不同的方法來做類似的事情(預(yù)加載、急切加載、聯(lián)接和包含?),我還不知道這些都是什么,但也許我以后會(huì)知道的。
一個(gè)有趣的 Rails 功能:腳手架!
Rails 有一個(gè)叫 rails
的命令行工具,它可以生成很多代碼。例如,我想添加一個(gè) Topic
模型/控制器。我不用去想在哪里添加所有的代碼,可以直接運(yùn)行
rails generate scaffold Topic title:text
并生成了一堆代碼,這樣我已經(jīng)有了基本的端點(diǎn)來創(chuàng)建/編輯/刪除主題(Topic
)。例如,這是我的現(xiàn)在的主題控制器,其中大部分我沒有寫(我只寫了高亮的 3 行)。我可能會(huì)刪除很多內(nèi)容,但是有一個(gè)起點(diǎn),讓我可以擴(kuò)展我想要的部分,刪除我不想要的部分,感覺還不錯(cuò)。
數(shù)據(jù)庫遷移!
rails
工具還可以生成數(shù)據(jù)庫遷移! 例如,我決定要?jiǎng)h除帖子中的 title
字段。
下面是我要做的:
rails generate migration RemoveTitleFromPosts title:string
rails db:migrate
就是這樣 —— 只要運(yùn)行幾個(gè)命令行咒語就可以了! 我運(yùn)行了幾個(gè)這樣的遷移,因?yàn)槲腋淖兞藢?duì)我的數(shù)據(jù)庫模式的設(shè)想。它是相當(dāng)直接的,到目前為止 —— 感覺很神奇。
當(dāng)我試圖在一列中的某些字段為空的地方添加一個(gè)“不為空”(not null
)約束時(shí),情況就變得有點(diǎn)有趣了 —— 遷移失敗。但我可以修復(fù)違例的記錄,并輕松地重新運(yùn)行遷移。
今天就到這里吧!
明天,如果我有更多的進(jìn)展,也許我會(huì)把它放在互聯(lián)網(wǎng)上。