常在 controller 裡看到 before_action,它是一個方法嗎? 跟一般用 def 定義的有何不同?
在 Rails 專案中,常會在 Controller 裡看到這樣的寫法:
class ProductController < ApplicationController
before_action :find_product, only: [:show, :edit, :update, :destroy]
# .. 中略
private
def find_product
@product = Product.find_by(id: params[:id])
end
end
這是指在執行特定 Action 之前,先去執行 find_product
方法。
在 Model 裡也常看到類似的寫法:
class Article < ApplicationRecord
before_save :encrypt_password
validates :title, presence: true
private
def encrypt_password
# ....
end
end
這是說在資料儲存之前,先執行 encrypt_password
方法對密碼進行加密。
在一般的 Ruby 專案裡也常會看到這樣的寫法:
class Cat
attr_accessor :age, :name
end
kitty = Cat.new
kitty.name = "nancy"
kitty.age = 10
puts kitty.name # => nancy
puts kitty.age # => 10
所以,在 Controller 裡的 before_action
或是 Model 裡 before_save
及 validates
,或是那個 attr_accessor
到底是什麼來歷? 感覺好像是什麼設定還是屬性,或是關鍵字之類的東西?
類別方法
其實,這些看起來像設定或是屬性的東西,它們不過就是類別方法罷了。
class Cat
def self.my_attr_accessor(*field_name)
# ... 實作
end
my_attr_accessor :age, :name
end
跟寫一般的方法沒什麼不同,一樣是使用 def
這個關鍵字來定義,只是在定義類別方法的時候,需要在方法名字前面加個 self
,這樣就可以定義出類別方法(事實上是 Singleton Method),然後就可以直接在類別裡面使用。
至於這些類別方法裡面的實作稍微有些複雜,有的需要知道怎麼操作 Block,有的還需要知道怎麼動態的定義方法(例如使用 define_method
),我們另外再開一篇來介紹。
關鍵字?
有些人以為 private
、protected
這些語法是關鍵字,事實上這些都只是方法罷了(Ruby 什麼東西沒有,方法最多了)。
Ruby 裡的關鍵字不算太多,有興趣可翻 Ruby 的原始碼出來看看,Ruby 大概定義了 40 個左右的關鍵字,大概就是 if
、else
、def
、class
之類的。參考連結
但即使是關鍵字也不表示全部不能用,你要拿來定義方法也是可以的,例如:
def if
puts "this is a if"
end
在定義的時候不會出錯,但使用的時候就沒辦法了:
if()
會得到錯誤訊息如下:
-:51: syntax error, unexpected end-of-input
shell returned 1
因為 Ruby 在判讀語法的時候,期待 if
後面還有一些東西,所以 Ruby 認為你還沒寫完然後被判定成語法錯誤。但如果是包在類別裡的話:
class Joke
def if
puts "this is a if"
end
end
Joke.new.if
這樣就能正常執行了 :)
工商服務
實體課程:Ruby on Rails 實戰課程
線上課程:五倍學院線上課程