ActiveRecordモデルのカスタムバリデーションメソッドを共有したいんです
委譲でなく。エラーはerrorsに書き込みたいから……と考えるとバリデーションの委譲はたぶん面倒臭い。
だからMixinしてやる。こういうやり口ってRailsのベストプラクティスでまとめられていたりしそう。
ruby 1.9.2p290 (2011-07-09) [i386-mingw32] activerecord (3.1.0)
Departmentに、manager_idに関するカスタムバリデーションメソッドsample
があるとする。
class Department < ActiveRecord::Base self.primary_key = :department_id belongs_to :location has_many :employees has_many :job_histories def manager Employee.where(employee_id: manager_id) end validate :sample def sample if manager_id <= 100 errors[:manager_id] = 'manager_id must be greater than 100' end end end dept = Department.new dept.manager_id = 99 p dept.valid? ? 'correct' : dept.errors.full_messages # => ["Manager manager_id must be greater than 100"]
おなじことを他のモデルでもやりたい場合、この例だとしょぼいから何とでもなりそうだが、バリデーション内容が複雑になればなるほどメソッドを共用したくなる。
そしたらModuleを作ってincludeしてしまえばよい。
class Department < ActiveRecord::Base self.primary_key = :department_id belongs_to :location has_many :employees has_many :job_histories def manager Employee.where(employee_id: manager_id) end validate :sample module CustomValidateModule def sample if manager_id <= 100 errors[:manager_id] = 'manager_id must be greater than 100' end end end include CustomValidateModule end class Employee < ActiveRecord::Base self.primary_key = :employee_id belongs_to :job belongs_to :department has_many :job_histories def manager Employee.where(employee_id: manager_id) end def members Employee.where(manager_id: employee_id) end validate :sample include Department::CustomValidateModule end dept = Department.new dept.manager_id = 99 p dept.valid? ? 'correct' : dept.errors.full_messages # => ["Manager manager_id must be greater than 100"] emp = Employee.new emp.manager_id = 99 p emp.valid? ? 'correct' : emp.errors.full_messages # => ["Manager manager_id must be greater than 100"]
(^ω^)にこっ