本文是一個Rails新手的學習筆記,主要是對過去一個月中學習內容的總結,包括:css
Agile Web Development with Rails 4html
Rails 101web
Rails for Zombies算法
水平有限, 錯誤再所不免(這也是我寫出來的緣由啦 :D), 還請諸位多多指教.數據庫
Rails 的開發速度很是快,但學習速度是很慢的。DHH曾經提到過:相比learnability,他更看重usability。DHH的15分鐘開發博客程序確實激動人心,可是不通過全面的學習,想要作出合格可用的產品是不現實的。bootstrap
學習Rails究竟是在學習什麼? 在我看來,主要是如下幾個:數組
這是學習任何一個web框架,都要完成的任務。Rails相比其餘框架,須要學習的點就是MVC 和 routes 文件的寫法。瀏覽器
Rails框架強制你使用MVC模式進行開發,那什麼是真正的MVC呢?那就是:ruby
用戶請求的永遠是controller,服務器返回給瀏覽器的永遠是view.服務器
以用戶註冊爲例,直覺的作法是用戶點擊首頁的註冊連接,轉到有表格的view,用戶填寫信息以後submit,請求轉到controller中的特定action,處理請求以後根據結果轉回註冊頁面或者自動登陸到首頁。
這種作法並無徹底符合MVC,由於有經過硬編碼的連接實現的view到view的跳轉,Rails的作法是這樣的:
點擊首頁的註冊連接,跳轉到users_controller
的 new,這個action計算用戶須要填寫的信息,初始化一個空的對象,轉到new_html這個view,用戶填寫表格以後submit,請求轉給create這個action,處理請求以後根據結果 redirect_to 到 new (重定向會讓瀏覽器再次向服務器發起對controller下 new 的請求)或者自動登陸到首頁。
永遠是 view -> controller -> view 的處理流程。
這並非一個好例子,或許我該舉一些「不在view中寫業務邏輯、保持controller精簡」之類的最佳實踐,可是它們都被舉爛了,我也就再也不多說,我舉得這個例子或許能讓你對MVC有多一些的思考。
routes.rb
這個文件無疑是任何 Rails 項目的靈魂, 我獲得的建議是: 若是你打算研究一個 Rails 開源項目, 要打開的第二個文件永遠是routes.rb
, 第一個固然是Gemfile
啦, :D.
這個文件的兩個基本做用:
new_user_path
這樣的寫法,避免出現硬編碼的連接controller
中的action
相對應.這就牽扯到了Rrails的一個重要特性: restful
. 之前寫Servlet
, 常常會有/getUser?id=3
這樣的連接, restful
的想法是, 既然自己已是GET
請求了, 連接何須再有get
呢. Rails就按照restful
的思路, 把連接變成了: GET users/:id
. 在使用該連接的時候, 用users_path(@user)
這樣的寫法來傳遞id
這個參數.
restful
固然還有更"高大上"的做用, 例如分佈式系統下的容錯性之類的, 可是對於新手, 這樣理解設計者的初衷就行了: 就是將updateUserInfo?id=3
deleteUser?id=4
這樣的連接, 轉成PUT users/3
DELETE users/3
.
新手常常搞不清楚path
的寫法, 尤爲是出現各類nested resources
的時候, 在終端輸入rake routes
, 就能夠看到了正確寫法了.
主要學習的點包括migration
, seeds.rb
, 表關係及查詢語句的編寫.
SQL無疑是很是好用的語言, 但有個致命的肯定: 三五人的小團隊, 沒有專門的DBA, 如何保證全部開發者的數據庫設計是一致的? 固然, 有許多的作法能夠解決這個問題, 這些作法中migration是最好的之一.
它的基本思路, 就是用ruby代碼來作數據庫設計(增長新的表, 增長索引, 改變某列的數據類型), 每次修改都放在單獨的良好命名的文件之中, 只要將其歸入版本管理, 經過rake db:migrate
命令, 就能夠保證全部開發者的數據庫設計師一致的.
同時藉助seeds.rb
文件, 保證全部開發者的測試數據是一致的.
也就是表之間的主外鍵關係以及三範式的知足. 在我短暫的Rails開發旅程中, 大多數時間都花費在數據庫設計上, 也使我對
程序 = 算法 + 數據結構
這一論斷愈來愈信服.
Rails 提供了諸多功能方便開發者申明表之間的主外鍵關係, 包括has_many
belongs_to
has_many_through
等, 合理地利用該特性能夠幫助你寫出可讀性很是好的代碼, 例如在這樣的主外鍵設計之下:
class Group < ActiveRecord::Base has_many :group_users has_many :members, :through => :group_users, :source => :user end class GroupUser < ActiveRecord::Base belongs_to :user belongs_to :group end class User < ActiveRecord::Base has_many :group_users has_many :participated_groups, :through => :group_users, :source => :group end
能夠用current_user.participated_groups
這樣十分天然的語句來獲取當前登陸用戶參加的社團.
這一點沒什麼好說的, 就兩點:
find_by
返回的是找到的第一個值這也是學習Rails中的很重要的一個點, 選擇Rrails是爲了快速開發, 那爲何不更快一點呢. devise
讓你一份實現登錄與註冊, 郵箱驗證, 密碼找回; bootstrap-rails
讓你兩分鐘提高網站的設計感; will_paginate
讓你再也不操心分頁的實現....
固然還有許多重要的點要學習, 可是都沒有上面幾個那樣有提綱挈領的做用. 都放到下一節當細節說吧.
主要就是Sublime Text
了, 有幾個插件很是好用, 明顯提升效率. 我裝了Emmet
, ERB Snippets
和Ruby on Rails snippets
三個插件, 主要是實現
PE
而後tab
能夠自動生成<%= -%>
ER
而後tab
能夠自動生成<% %>
ul>li*2>a
而後tab
能夠打出:<li><a href=""></a></li> <li><a href=""></a></li>
has_many
之類的, 你們自行查看其官網的cheat_sheet
scope :graveyard, where(:show_location => true , :location => 'graveyard')
給列添加索引, 以提高性能
class Tweet < ActiveRecord::Base has_one :location, :dependent => :destroy, :foreign_key => :tweeter_id end class Location < ActiveRecord::Base belongs_to :tweet, :foreign_key => :tweeter_id end
dependent: :destroy
來設置外鍵依賴避免 N+1 issue
使用 Zombie.includes(:brain).all
,來代替直接Zombie.all
, 而後view
中each打印zombie.brain
, 以提高性能
update_attributes和update是同樣的
參考這裏 rake, 也可使用rake -T
查看
rake db:schema:dump
, 能夠從如今的數據庫建立schema文件rake db:setup
. 三件事: 建立數據庫, 讀取schema文件, 從'seeds.rb'導入種子數據concerns/current_cart_rb
中, 一方面是其中的方法在各個controller中共享, 其次防止其中的方法被當作action來調用. 注意該文件夾下的文件都是autoload
的, 不須要顯式地寫include
.callback
使set_cart
執行的.class CartsController < ApplicationController before_action :set_cart, only: [:show, :edit, :update, :destroy] rescue_from ActiveRecord::RecordNotFound, with: :invalid_cart def index @carts = Cart.all end private def invalid_cart logger.error { "Attempt to access invalid cart #{params[:id]}" } redirect_to store_path, notice: 'Invalid cart!' end end module CurrentCart extend ActiveSupport::Concern private def set_cart @cart = Cart.find(session[:cart_id]) rescue ActiveRecord::RecordNotFound @cart = Cart.create session[:cart_id] = @cart.id end end
def new if @cart.line_items.empty? redirect_to store_url, notice: 'Your cart is empty.' return #redirect_to不會自動return end @order = Order.new end
-before_filter
就是舊版本中的 before_action
- build
就是new
的別名
- save!
會引起RecordInvalid
異常, 而save
會返回boolean
值
- nil?
判斷對象是否存在, 不存在的對象都是nil
的; empty?
判斷是否爲空字段,好比一個字符串是否爲空串,或者一個數組中是否有值;object.blank?
至關於o
bject.nil?||object.empty?`
- 在befor類的鉤子函數中,返回FALSE則不執行before後跟的操做, 此處容易出bug
能夠用errors.add(:base, 'Line Items present')
添加錯誤信息, 在controller中能夠經過@line_item.errors
來獲取.
能夠經過<body class='<%= controller.controller_name %>'>
來命名body的class, 方便scss的書寫.
#view中 <%= f.select :pay_type, Order::PAYMENT_TYPES, prompt: 'Select a payment method' %> # model中 PAYMENT_TYPES = ['Check', 'Credit Card', 'Purchase Order'] validates :pay_type, inclusion: PAYMENT_TYPES
button_to
默認是POST
請求, link_to
默認是GET
請求.