I am trying to write more modular code for my rails apps, so have started playing more with including modules in classes. I have basic understanding of their function, but i am finding it hard to keep them flexible while remaining DRY.
Here is a current example.
I have a module called Contactable. It has two very basic functions.
- Ensures the right contact columns are present in the DB.
- Validates certain fields.
Here it is
module Contactable
extend ActiveSupport::Concern
ERROR = 'please ensure necessary fields are in place'
included do
REQUIRED_DATABASE_FIELDS.map { |rdf| raise "#{rdf} not included. #{ERROR}" unless column_names.include?(rdf)}
REQUIRED_INPUT_FIELDS.map { |rif| validates rif.to_sym, presence: true}
end
end
I would like contactable to be comprised of three other modules (Phoneable, Emailable and Addressable) which contain the arrays of columns to require and fields to validate against. One I am working on right now is 'Addressable'
module Addressable
extend ActiveSupport::Concern
ERROR = 'please ensure necessary fields are in place'
REQUIRED_DATABASE_FIELDS = %w{address1
address2
address3
town
county
country
postcode}
REQUIRED_INPUT_FIELDS = %w{address1 postcode}
included do
REQUIRED_DATABASE_FIELDS.map { |rdf| raise "#{rdf} not included. #{ERROR}" unless column_names.include?(rdf)}
REQUIRED_INPUT_FIELDS.map { |rif| validates rif.to_sym, presence: true}
end
end
Obviously here there is duplication. However, if I include this module into contactable I avoid the need for some of the repetition but it means that Contactable will always include Phoneable and Emailable also. In some cases I might not want to validate or require these traits. Is there a way I can achieve this flexibility?