I am starting to use the concerns pattern in a project and as this is the first time using it, some questions came to mind. First of all, let me share the code snipet I am working on for clarification.
module Approvable
extend ActiveSupport::Concern
included do
#validations
validates :approval_status,
presence: true,
inclusion: { :in => NixusValidation::ValidApprovalStatuses, :message => :inclusion, unless: 'approval_status.blank?' }
#scopes:
scope :approved, -> { where(approvalStatus: NixusValidation::ApprovalStatuses::APPROVED) }
scope :pending, -> { where(approvalStatus: NixusValidation::ApprovalStatuses::PENDING) }
scope :unapproved, -> { where(approvalStatus: NixusValidation::ApprovalStatuses::UNAPPROVED) }
end
#INSTANCE METHODS
#methods:
def approved?()
self.approval_status == NixusValidation::ApprovalStatuses::APPROVED
end
end
This concern defines common characteristics of an "approvable" model, something that needs to be approved like a join request for example. Every approvable model in my project have 3 states, approved, pending and unapproved. Here are some of my doubts about the code I wrote.
For this concern to work, the model needs to have an approval_status attribute, which needs to be persisted somehow. Is this wrong? Should concerns only define behaviour like interfaces? If not, how can I enforce the existence of this attribute in Rails? Is there a way to tell the rails model generator to always include this attribute in approvable models without inheritance?
I also need to implement an approve() method, but every approvable class has its own approvement proccess. The only thing in common is that if everything goes ok approved?() should return true afterwards. Is there a way to enforce the existence of the approve() method if a class includes the Approvable concern?
Is this a good case to use concerns?
Hope I made myself clear.
Thanks in advance,
@Surya,
Thanks for the idea. Just to see if I got this right, you are suggesting that I should have an ApprovalStatus class with a polymorphic relation to :approvable.
Something like:
In this case the ApprovalStatus is the one that should handle the approvement business logic based on its caller right?