😸
ActionController::Parameters#requireを自作する
概要
https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-require を参考に、ActionController::Parameters#requireを自作します。
実装
seitou.rb
# frozen_string_literal: true
class Seitou
class ParameterMissing < StandardError; end
attr_reader :parameters
def initialize(parameters = {})
@parameters = parameters
end
def require(key)
return key.map { |k| require(k) } if key.is_a?(Array)
return_parameter = @parameters[key]
raise ParameterMissing if [nil, "\t"].include?(return_parameter) || return_parameter.empty?
self.class.new(return_parameter)
end
def ==(other)
@parameters == other.parameters
end
end
単体テスト
seitou_spec.rb
# frozen_string_literal: true
require_relative '../seitou'
RSpec.describe Seitou do
describe '#require' do
context 'when pass single key' do
it {
expect(described_class.new(person: { name: 'Francesco' }).require(:person)).to eq described_class.new({ name: 'Francesco' })
}
end
context 'when not pass single key' do
it {
expect do
described_class.new(person: { name: 'Francesco' }).require(:name)
end.to raise_error(described_class::ParameterMissing)
}
end
context 'when parameter is nothing' do
it {
expect { described_class.new.require(:person) }.to raise_error(described_class::ParameterMissing)
}
end
context 'when value is nil' do
it {
expect { described_class.new(person: nil).require(:person) }.to raise_error(described_class::ParameterMissing)
}
end
context 'when value is \t' do
it {
expect { described_class.new(person: "\t").require(:person) }.to raise_error(described_class::ParameterMissing)
}
end
context 'when value is {}' do
it {
expect { described_class.new(person: {}).require(:person) }.to raise_error(described_class::ParameterMissing)
}
end
context 'when given an array of keys' do
it {
expect(described_class.new(user: { name: :sidehara }, profile: { name: :sidehara }).require(%i[user profile]))
.to eq [described_class.new(name: :sidehara), described_class.new(name: :sidehara)]
}
end
context 'when fetch terminal values' do
it {
expect(described_class.new(person: { name: 'Francesco' }).require(:person).require(:name).parameters).to eq 'Francesco'
}
end
end
end
感想
次の点について実装を省いています。
- オブジェクトの存在確認
- 末端の値を取得する場合の挙動
次回は、この点について忠実に実装しようかと考えています。
Discussion