active-hash / active_hash

A readonly ActiveRecord-esque base class that lets you use a hash, a Yaml file or a custom file as the datasource
MIT License
1.21k stars 179 forks source link

Add built-in predicate methods for enum types in ActiveHash #319

Closed hatsu38 closed 2 months ago

hatsu38 commented 2 months ago

Description

When using ActiveHash with enum types, we often find ourselves writing repetitive predicate methods for each enum value. For example:

class PublicStatus < ActiveHash::Base
  include ActiveHash::Enum
  include ActiveHash::Associations

  self.data = [
    { id: 1, name: "Publish", type: "published" },
    { id: 2, name: "Draft", type: "drafted" },
    { id: 3, name: "Archive", type: "archived" }
  ]

  enum_accessor :type

  def published?
    id == PublicStatus::PUBLISHED.id
  end

  def drafted?
    id == PublicStatus::DRAFTED.id
  end

  def archived?
    id == PublicStatus::ARCHIVED.id
  end
end

These methods are commonly used but require manual implementation for each enum value. It would be beneficial if ActiveHash could automatically generate these status check methods based on the defined enum values.

Proposed Solution

Enhance ActiveHash to automatically generate status check methods for enum values. This could be implemented as follows:

When enum_accessor :type is called, automatically generate methods for each enum value. The generated methods would follow the pattern {enum_value}? and return a boolean indicating whether the current object matches that enum value.

Example Usage

With this enhancement, the above code could be simplified to:

class PublicStatus < ActiveHash::Base
  include ActiveHash::Enum
  include ActiveHash::Associations

  self.data = [
    { id: 1, name: "Publish", type: "published" },
    { id: 2, name: "Draft", type: "drafted" },
    { id: 3, name: "Archive", type: "archived" }
  ]

  enum_accessor :type
  # No need to manually define published?, drafted?, archived? methods
end

status = PublicStatus.find(1)
status.published? => true
status.drafted?   => false
status.archived?  => false