コールバックによる制御
コールバックとは
特定の処理に引っ掛けて別の処理を呼ぶことをコールバックと言います
メリット
- 前処理、後処理などを宣言的に書くことができる
- 必ず保存後に行いたい処理がある時に、実行の漏れを防ぐことができる
コールバックの基本的な使い方
(例)
本の名前を保存する前に、名前に"Dog"が含まれていた場合
"Dog Cute"と文字列を置き換える
class Book < ApplicationRecord
略
before_validation do
self.name = self.name.gsub(/Dog) do |matched|
"Dog Cute #{matched}"
end
end
# メソッドを使って書くこともできます
before_validation :add_Cute_to_dog(独自メソッド)
def add_Cute_to_dog
self.name = self.name.gsub(/Dog/) do |matched|
"Dog Cute #{matched}"
end
end
end
上記の記述のgsubメソッドとは何?
gsubメソッド
gsubメソッドはマッチしたすべての部分を特定の文字列に置換します。
パターンには文字列や正規表現が使えます。
irb(main):001:0> Book.create(
irb(main):002:1* name: "My Dog",
irb(main):003:1* publsiher: Publisher.find(1),
irb(main):004:1* price: 1000,
irb(main):005:1* )
[["name", "My Dog Cute Dog"],
["price", 1000],
["created_at", "2022-07-28 10:00:58.584937"],
["updated_at", "2022-07-28 10:00:58.584937"],
["publisher_id", 1]
]
ActiveRecord:Enum
ActiveRecordにenum型とは
モデルの数値のカラムに対してプログラム上で扱えるように名前を定義してくれるもの
例
本に販売の状況に関する状況を追加する場合
販売の状況はテーブルに定義する際に数ないバリエーションのため、文字列として保存するのが効率的になります
このような数値を扱うコードをプログラムで扱う場合
下記のようになります。
RESERVATION = 0 予約受付
NOW_ONSALE = 1 発売中
END_SALE = 発売終了
このような時に役に立つのがenum型になります
Bookモデルに販売状況のカラムを追加し、値を管理する方法としてenum型を定義します
rails g migration AddStatusToBooks sales_status:integer
rails db:migrate
次に、enumクラスメソッドにカラム名と対応する値を定義する。
定義する値はハッシュ形式で名称と値の組み合わせで定義。
または、名称を文字列かシンボルの配列とすることができる。
class Book < ApplicationRecord
enum sales_status: {
reservation: 0, # 予約受付中
now_on_sale: 1, # 発売中
end_of_sales: 2, # 発売終了
}
上記のようにし、データを保存してみると
irb(main):013:0> Book.create(
irb(main):014:1* name: "samplebook",
irb(main):015:1* publisher: Publisher.find(1),
irb(main):016:1* sales_status: 1,
irb(main):017:1* price: 1000,
irb(main):018:1* )
<Book id: 3, name: "samplebook",
published_on: nil,
price: 1000,
created_at: "2022-07-30 09:37:44.399443000 +0000",
updated_at: "2022-07-30 09:37:44.399443000 +0000",
publisher_id: 1,
sales_status: "now_on_sale"
先ほどのカラムの出力結果を見てみると、
保存の際に数値で行なったが定義した文字列で戻ってきている
このようにenum型を利用すると、コード上で分かりやすいシンボルなどで指定しつつ、
DB上の定義に合わせて保存することが可能となります。
Enumで定義された状態を見たい場合
ステータスごとに述語メソッドで状態を確認する子おtができる
irb(main):013:0> book.now_on_sale?
=> true
irb(main):015:0> book.end_of_sales?
=> false
DBに保存されている実際の値を確認したい場合
カラム名_before_type_castメソッドで確認することができます。
irb(main):016:0> book.sales_status_before_type_cast
=> 1
また、enumの定義を確認したい場合、
カラム名の複数形メソッドをクラスメソッドとして呼び出します
irb(main):019:0> Book.sales_statuses
=> {"reservation"=>0, "now_on_sale"=>1, "end_of_sales"=>2}