本文是我在閱讀 Ruby on Rails 教程的簡體中文版時所作的摘錄,以及學習時尋找的補充知識。補充知識主要來自於 Ruby on Rails 實戰聖經。css
在最新版 Rails 中,靜態文件能夠放在三個標準文件夾中,並且各有各的用途:html
app/assets
:當前應用的資源文件;lib/assets
:開發團隊本身開發的代碼庫使用的資源文件;vendor/assets
:第三方代碼庫使用的資源文件;*= require_tree .
會把 app/assets/stylesheets
文件夾中的全部 CSS 文件(包含子文件夾中的文件)都引入應用的 CSS 。數據庫
*= require_self
會把 application.css
這個文件中的 CSS 也加載進來。數組
(預處理器引擎)按照擴展名的順序從右向左處理瀏覽器
使用 Asset Pipeline,生產環境中應用全部的樣式都會集中到一個 CSS 文件中(application.css
),全部 JavaScript 代碼都會集中到一個 JavaScript 文件中(application.js
),並且還會壓縮這些文件,刪除沒必要要的空格,減少文件大小。安全
...「回調」(callback),在 Active Record 對象生命週期的特定時刻調用。如今,咱們要使用的回調是 before_save
,在用戶存入數據庫以前把電子郵件地址轉換成全小寫字母形式。cookie
其餘的回調有:save
、valid
、before_validation
、validate
、after_validation
、before_save
、before_create
、create
、after_create
、after_save
、after_commit
session
add_index :users, :email, unique: true
上述代碼調用了 Rails 中的 add_index
方法,爲 users
表中的 email
列創建索引。索引自己並不能保證惟一性,因此還要指定 unique: true
。app
add_index :microposts, [:user_id, :created_at]
咱們把 user_id
和 created_at
放在一個數組中,告訴 Rails 咱們要建立的是「多鍵索引」(multiple key index),所以 Active Record 會同時使用這兩個鍵。post
爲了獲得特定的順序,咱們要在 default_scope
方法中指定 order
參數,按 created_at
列的值排序
default_scope -> { order(created_at: :desc) }
dependent: :destroy
的做用是在用戶被刪除的時候,把這個用戶發佈的微博也刪除。
:dependent
能夠有三種不一樣的刪除方式,分別是::destroy
、:delete
、:nullify
has_many :active_relationships, class_name: "Relationship", foreign_key: "follower_id", dependent: :destroy belongs_to :follower, class_name: "User" belongs_to :followed, class_name: "User" has_many :following, through: :active_relationships, source: :followed
指定表名和主鍵:
class Category < ActiveRecord::Base self.table_name = "your_table_name" self.primary_key = "your_primary_key_name" end
書中多對多的關係自定義了不少名字,若是採用Rails默認命名,是下面的樣子:
class Event < ActiveRecord::Base has_many :event_groupships has_many :groups, :through => :event_groupships end class EventGroupship < ActiveRecord::Base belongs_to :event belongs_to :group end class Group < ActiveRecord::Base has_many :event_groupships has_many :events, :through => :event_groupships end
固件的做用是爲測試數據庫提供示例數據
test/fixtures/users.yml michael: name: Michael Example email: michael@example.com password_digest: <%= User.digest('password') %>
建立了一個有效用戶固件後,在測試中可使用下面的方式獲取這個用戶:
user = users(:michael)
其中,users
對應固件文件 users.yml
的文件名,:michael
是代碼清單 8.19 中定義的用戶。
test "login with valid information" do get login_path post login_path, session: { email: @user.email, password: 'password' } assert_redirected_to @user follow_redirect! assert_template 'users/show' assert_select "a[href=?]", login_path, count: 0 assert_select "a[href=?]", logout_path assert_select "a[href=?]", user_path(@user) end end
在這段代碼中,咱們使用 assert_redirected_to @user
檢查重定向的地址是否正確;使用 follow_redirect!
訪問重定向的目標地址。還確認頁面中有零個登陸連接,從而確認登陸連接消失了:
assert_select "a[href=?]", login_path, count: 0
count: 0
參數的目的是,告訴 assert_select
,咱們指望頁面中有零個匹配指定模式的連接。(代碼清單 5.25中使用的是 count: 2
,指定必須有兩個匹配模式的連接。)
在模型中調用這個方法(has_secure_password
)後,會自動添加以下功能:
在數據庫中的 password_digest
列存儲安全的密碼哈希值;
(經過下面遷移得到:)
add_column :users, :password_digest, :string
得到一對「虛擬屬性」,password
和 password_confirmation
,並且建立用戶對象時會執行存在性驗證和匹配驗證;
User.new(name: "Example User", email: "user@example.com", password: "foobar", password_confirmation: "foobar")
得到 authenticate
方法,若是密碼正確,返回對應的用戶對象,不然返回 false
。
user = User.find_by(email: "mhartl@example.com") user.authenticate("not_the_right_password")
bcrypt
驗證記憶令牌BCrypt::Password.new(remember_digest).is_password?(remember_token)
private def user_params params.require(:user).permit(:name, :email, :password, :password_confirmation) end @user = User.new(user_params)
必須只容許經過請求傳入可安全編輯的屬性。admin
並不在容許使用的屬性列表中。這樣就能夠避免用戶取得網站的管理權。
通過上述分析,咱們計劃按照下面的方式實現持久會話:
Cookie的用法:
cookies[:remember_token] = { value: remember_token, expires: 20.years.from_now.utc }
另外一種簡寫:
cookies.permanent[:remember_token] = remember_token
加密Cookie:
cookies.signed[:user_id] = user.id
爲了實現圖 9.6 中的轉向功能,咱們要在用戶控制器中使用「事前過濾器」。事前過濾器經過 before_action
方法設定,指定在某個動做運行前調用一個方法。
默認狀況下,事前過濾器會應用於控制器中的全部動做,因此在上述代碼中咱們傳入了 :only
參數,指定只應用在 edit
和 update
動做上。
<%= render @users %>
Rails 會把 @users
看成一個 User
對象列表,傳給 render
方法後,Rails 會自動遍歷這個列表,而後使用局部視圖 _user.html.erb
渲染每一個對象。
params
哈希中包含一個基於複選框狀態的值。若是勾選了複選框,params[:session][:remember_me]
的值是 '1',不然是 '0'。
代碼清單 9.2 和代碼清單 7.13 都使用了相同的 form_for(@user)
來構建表單,那麼 Rails 是怎麼知道建立新用戶要發送 POST
請求,而編輯用戶時要發送 PATCH
請求的呢?這個問題的答案是,經過 Active Record 提供的 new_record?
方法檢測用戶是新建立的仍是已經存在於數據庫中
form_for(@user)
的做用是讓表單向 /users
發起 POST
請求。對會話來講,咱們須要指明資源的名字以及相應的 URL:
form_for(:session, url: login_path)
form_for
和form_tag
的區別:
一種是對應到Model物件的新增、修改,我們會使用form_for
這個Helper。它的好處在於透過傳入Model物件,能夠在修改的時候自動幫你將預設值帶入。例如我們已經在Part1使用過的event
表單:
<%= form_for @event do |f| %> <%= f.text_field :name %> <%= f.submit %> <% end %>
另外一種是就是沒有對應Model的表單,我們使用form_tag
這個方法。例如:
<%= form_tag "/search" do %> <%= text_field_tag :keyword %> <%= submit_tag %> <% end %>
和form_tag
有些類似,可是其中不須要傳Block變數f
,其中的欄位Helper須要多加_tag
結尾。不像form_for
的欄位名稱必定要是Model的屬性之一,在form_tag
之中的欄位名稱則徹底不受限。
resources :users do member do get :following, :followers end end
設定上述路由後,獲得的 URL 地址相似 /users/1/following
和 /users/1/followers
這種形式。
除此以外,咱們還可使用 collection
方法,但 URL 中就沒有用戶 ID 了。
resources :users do collection do get :tigers end end
獲得的 URL 是 /users/tigers
另外還有這種使用方法:
resources :projects do resources :tasks end
獲得的URL如projects/123/tasks
和projects/123/tasks/123
。
只要把 form_for
改爲 form_for…, remote: true
,Rails 就會自動使用 Ajax 處理表單。
同理於超連結 link_to
,按鈕 button_to
加上:remote => true
參數也會變成 Ajax。