module InitAttributes def self.included(base) base.send(:include, InstanceMethods) base.extend(ClassMethods) end module InstanceMethods def initialize(attributes) init_instance_variables(self.class.accessor_attributes, attributes) init_instance_variables(self.class.reader_attributes, attributes) end private def init_instance_variables(required_attributes, given_attributes) required_attributes.each do |attr| instance_variable_set("@#{attr}", given_attributes.fetch(attr)) end end end module ClassMethods def accessor_attributes @accessor_attributes ||= [] end def reader_attributes @reader_attributes ||= [] end private def init_attr_accessor(*attributes) attr_accessor(*attributes) @accessor_attributes = attributes end def init_attr_reader(*attributes) attr_reader(*attributes) @reader_attributes = attributes end end end class Akira include InitAttributes init_attr_reader :one init_attr_accessor :two def do_something puts 'Doing something...' end end ls Akira # InitAttributes::ClassMethods#methods: accessor_attributes reader_attributes # Akira#methods: do_something one two two= # instance variables: @accessor_attributes @reader_attributes akira = Akira.new(one: 1, two: 2) # => # ls akira # Akira#methods: do_something one two two= # instance variables: @one @two Akira.new(one: 1) # => KeyError: key not found: :two