module EnumHelp

  module I18n

    # overwrite the enum method
    def enum( definitions )
      super( definitions )
      definitions.each do |name, _|
        Helper.define_attr_i18n_method(self, name)
        Helper.define_collection_i18n_method(self, name)
      end
    end

    def self.extended(receiver)
      # receiver.class_eval do
      #   # alias_method_chain :enum, :enum_help
      # end
    end

  end

  module Helper

    def self.define_attr_i18n_method(klass, attr_name)
      attr_i18n_method_name = "#{attr_name}_i18n"

      klass.class_eval <<-METHOD, __FILE__, __LINE__
      def #{attr_i18n_method_name}
        enum_label = self.send(:#{attr_name})
        if enum_label
          ::EnumHelp::Helper.translate_enum_label(self.class, :#{attr_name}, enum_label)
        else
          nil
        end
      end
      METHOD
    end

    def self.define_collection_i18n_method(klass, attr_name)
      collection_method_name = "#{attr_name.to_s.pluralize}"
      collection_i18n_method_name = "#{collection_method_name}_i18n"

      klass.instance_eval <<-METHOD, __FILE__, __LINE__
      def #{collection_i18n_method_name}(*args)
        options = args.extract_options!
        collection = args[0] || send(:#{collection_method_name})
        collection.except! options[:except] if options[:except]

        collection.map do |label, value|
          [::EnumHelp::Helper.translate_enum_label(self, :#{attr_name}, label), value]
        end.to_h
      end
      METHOD
    end

    def self.translate_enum_label(klass, attr_name, enum_label)
      ::I18n.t("enums.#{klass.to_s.underscore}.#{attr_name}.#{enum_label}", default: enum_label)
    end

  end
end

module EnumHelp
  module I18n

    # overwrite the enum method
    def enum( definitions )
      klass = self
      super( definitions )
      definitions.each do |name, values|
        # def status_i18n() statuses.key self[:status] end
        i18n_method_name = "#{name}_i18n".to_sym
        define_method(i18n_method_name) do
          enum_value = self.send(name)
          if enum_value
            ::I18n.t("enums.#{klass.to_s.underscore}.#{name}.#{enum_value}", default: enum_value)
          else
            nil
          end
        end
      end
    end


    def self.extended(receiver)
      # receiver.class_eval do
      #   # alias_method_chain :enum, :enum_help
      # end
    end

  end
end


--- 
+++ 
@@ -1,24 +1,15 @@
 module EnumHelp
+
   module I18n
 
     # overwrite the enum method
     def enum( definitions )
-      klass = self
       super( definitions )
-      definitions.each do |name, values|
-        # def status_i18n() statuses.key self[:status] end
-        i18n_method_name = "#{name}_i18n".to_sym
-        define_method(i18n_method_name) do
-          enum_value = self.send(name)
-          if enum_value
-            ::I18n.t("enums.#{klass.to_s.underscore}.#{name}.#{enum_value}", default: enum_value)
-          else
-            nil
-          end
-        end
+      definitions.each do |name, _|
+        Helper.define_attr_i18n_method(self, name)
+        Helper.define_collection_i18n_method(self, name)
       end
     end
-
 
     def self.extended(receiver)
       # receiver.class_eval do
@@ -27,5 +18,44 @@
     end
 
   end
+
+  module Helper
+
+    def self.define_attr_i18n_method(klass, attr_name)
+      attr_i18n_method_name = "#{attr_name}_i18n"
+
+      klass.class_eval <<-METHOD, __FILE__, __LINE__
+      def #{attr_i18n_method_name}
+        enum_label = self.send(:#{attr_name})
+        if enum_label
+          ::EnumHelp::Helper.translate_enum_label(self.class, :#{attr_name}, enum_label)
+        else
+          nil
+        end
+      end
+      METHOD
+    end
+
+    def self.define_collection_i18n_method(klass, attr_name)
+      collection_method_name = "#{attr_name.to_s.pluralize}"
+      collection_i18n_method_name = "#{collection_method_name}_i18n"
+
+      klass.instance_eval <<-METHOD, __FILE__, __LINE__
+      def #{collection_i18n_method_name}(*args)
+        options = args.extract_options!
+        collection = args[0] || send(:#{collection_method_name})
+        collection.except! options[:except] if options[:except]
+
+        collection.map do |label, value|
+          [::EnumHelp::Helper.translate_enum_label(self, :#{attr_name}, label), value]
+        end.to_h
+      end
+      METHOD
+    end
+
+    def self.translate_enum_label(klass, attr_name, enum_label)
+      ::I18n.t("enums.#{klass.to_s.underscore}.#{attr_name}.#{enum_label}", default: enum_label)
+    end
+
+  end
 end
-
Create a dynamic method to translate enum collections

For a field named "status" we now have a "Foo.statuses_i18n" method,
which is similar to the existing "foo_instance.status_i18n".

Refactored the code to keep everything understandable with the new
changes. It now uses "instance_eval" and "class_eval" with string arguments,
which is faster than with blocks. Helper methods were placed in a distinct
module to avoid ActiveRecord::Base namespace pollution.
