sendメソッドとは
オブジェクトのメソッド name を args を引数にして呼び出し、メソッドの実行結果を返します。ブロック付きで呼ばれたときはブロックもそのまま引き渡します
Ruby 3.1 リファレンスマニュアル
メソッドを引数を持って呼び出せる。似たものにpublic_methodがあるが違いはprivateメソッドを呼び出せるかの違い。
特徴
Animalsコントローラーにあるプライベートメソッドpri_aをテストしたい時
# コントローラー
class AnimalsController < ApplicationController
private
def pri_a(x)
p "プライベート#{x}"
end
end
# テスト
test "pri_aの返り値がプライベート3であること" do
animal = AnimalsController.new
result = animal.send(:pri_a, 3)
assert_equal "プライベート3", result
end
カラムがnilであればエラーが出ることを確認したい時
# モデル
class Animal
with_options presence: true do
validates :name
validates :age
validates :from
end
end
# テスト
test "カラムがnilであれば保存できないこと" do
animal = Animal.new
%w[name age from].each do |colmun|
animal.send("#{column}=", nil)
assert_not animal.valid?
end
end
#以下と同じ意味
test "nameがnilであれば保存できないこと" do
animal = Animal.new
animal.name = nil
assert_not animal.valid?
end
test "ageがnilであれば保存できないこと" do
animal = Animal.new
animal.age = nil
assert_not animal.valid?
end
test "fromがnilであれば保存できないこと" do
animal = Animal.new
animal.from = nil
assert_not animal.valid?
end
条件によって呼び出すメソッドを変更したい時。asiaレコードやeuropeレコードを追加しても呼び出し方は変わらない。
class Record
attr_accessor :region
def world_record
# 処理
end
def japan_record
#処理
end
end
record = Record.new
record.region = "world"
if record.region == "world"
record.send("#{record.region}_record")
elsif record.region == "japan"
record.send("#{record.region}_record")
else
raise "not correct region"
end
まとめ
プライベートメソッドを直接叩いてテストできるのは便利だと感じた。また、条件によって呼び出すメソッドを変えたり(動的)したい場合も使えそう。
ただし、ユーザーが入力した(外部から来た)値等をsendメソッドで使うことは脆弱性の面から避けた方が良いと思いました。