概要
RailsのModelは、通常DBと結びついていないと使えないが、
データソースをDBではなく外部APIなどに変更し、
validation機能はそのまま使いたい。
ActiveModel::ModelをMixInしてvalidation機能を有効にし、
callbackでvalidateすることで実現する。
環境
- rails 5.0.0.1
- ruby 2.3.1
ソースコード例
ActiveModel::Model
をMixIn
これで通常のModelと同様にvalidate機能を利用できる。
自作validationも使えるようになる。
app/model/sample.rb
class Sample
# MixIn
include ActiveModel::Model
attr_accessor :name, :email, :age
# before_saveを使うための記述
define_model_callbacks :save
# callbackで実行するmethodを指定
before_save :form_validation
# validations
validates :name, presence: true, strict: true
# email: trueは自作validation
validates :email, email: true, presence: true, strict: true
validates :age, presence: true, strict: true
# method例
def all
run_callbacks :save do
'Your profile: #{name}, #{age}'
end
end
# method例
def find(id)
run_callbacks :save do
%Q(sample data: #{id})
end
end
# callback用 validation
private
def form_validation
self.valid?
#unless self.valid?
# self.errors.add(:attribute, self.errors.full_messages, strict: true)
#end
end
end
rspec
RSpec.describe Sample, type: :model do
describe 'Sample validation' do
context 'with the all parameters' do
subject { Sample.new(name: 'MyName', age: 17) }
it "returns no error" do
expect { subject.valid? }.not_to raise_error
end
end
context 'without any parameter' do
subject { Sample.new }
it "returns StrictValidationFailed" do
expect { subject.valid? }.to raise_error(ActiveModel::StrictValidationFailed)
end
it "returns StrictValidationFailed with message" do
expect { subject.valid? }.to raise_error(ActiveModel::StrictValidationFailed, 'Name translation missing: ja.activemodel.errors.models.sample.attributes.name.blank')
end
end
context 'with name without age' do
subject { Sample.new(name: 'MyName') }
it "returns StrictValidationFailed" do
expect { subject.valid? }.to raise_error(ActiveModel::StrictValidationFailed)
end
it "returns StrictValidationFailed with message" do
expect { subject.valid? }.to raise_error(ActiveModel::StrictValidationFailed, 'Age translation missing: ja.activemodel.errors.models.sample.attributes.age.blank')
end
end
end
describe 'Methods', type: :query do
subject { Sample.new(name: 'MyName', age: 17) }
describe 'all' do
it 'returns text' do
expect(subject.all).to eq('Your profile: MyName, 17')
end
end
end
end