Skip to content

Commit

Permalink
Add flexible enum support to ActiveHash::Enum
Browse files Browse the repository at this point in the history
- Implement `enum` method to support both array and hash-style definitions
- Allow predicate methods generation for enum values
- Support Rails-like enum syntax: `enum status: [:draft, :published, :archived]`
- Support custom value mapping: `enum action: { like: 'LIKE', comment: 'COMMENT', ... }`
- Add comprehensive tests for both enum definition styles

This enhancement allows ActiveHash::Enum to handle enum definitions similar to
Rails, improving compatibility and ease of use. It provides a more flexible
way to define and use enums in ActiveHash models.
  • Loading branch information
hatsu38 committed Aug 30, 2024
1 parent cd64cf3 commit 22147a3
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
11 changes: 11 additions & 0 deletions lib/enum/enum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ def enum_accessor(*field_names)
reload
end

def enum(columns)
columns.each do |column, values|
values = values.zip(values.map(&:to_s)).to_h if values.is_a?(Array)
values.each do |method, value|
define_method("#{method}?") do
send(column) == value
end
end
end
end

def insert(record)
super
set_constant(record) if defined?(@enum_accessors)
Expand Down
67 changes: 67 additions & 0 deletions spec/enum/enum_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,73 @@ class Neighborhood < ActiveHash::Base
expect(Movie::THE_INFORMANT.name).to eq('The Informant!')
expect(Movie::IN_OUT.name).to eq('In & Out')
end

describe "enum(columns)" do
it "defines a predicate method for each value in the enum" do
Article = Class.new(ActiveHash::Base) do
include ActiveHash::Enum

self.data = [
{ name: 'Article 1', status: 'draft'},
{ name: 'Article 2', status: 'published'},
{ name: 'Article 3', status: 'archived'}
]

enum_accessor :name

enum status: [:draft, :published, :archived]
end

expect(Article::ARTICLE_1.draft?).to be_truthy
expect(Article::ARTICLE_1.published?).to be_falsey
expect(Article::ARTICLE_1.archived?).to be_falsey

expect(Article::ARTICLE_2.draft?).to be_falsey
expect(Article::ARTICLE_2.published?).to be_truthy
expect(Article::ARTICLE_2.archived?).to be_falsey

expect(Article::ARTICLE_3.draft?).to be_falsey
expect(Article::ARTICLE_3.published?).to be_falsey
expect(Article::ARTICLE_3.archived?).to be_truthy
end

it "defines a predicate method for each value in the enum" do
NotifyType = Class.new(ActiveHash::Base) do
include ActiveHash::Enum

self.data = [
{ name: 'Like', action: 'LIKE'},
{ name: 'Comment', action: 'COMMENT'},
{ name: 'Follow', action: 'FOLLOW'},
{ name: 'Mention', action: 'MENTION'}
]

enum_accessor :name

enum action: { like: 'LIKE', comment: 'COMMENT', follow: 'FOLLOW', mention: 'MENTION' }
end

expect(NotifyType::LIKE.like?).to be_truthy
expect(NotifyType::LIKE.comment?).to be_falsey
expect(NotifyType::LIKE.follow?).to be_falsey
expect(NotifyType::LIKE.mention?).to be_falsey

expect(NotifyType::COMMENT.like?).to be_falsey
expect(NotifyType::COMMENT.comment?).to be_truthy
expect(NotifyType::COMMENT.follow?).to be_falsey
expect(NotifyType::COMMENT.mention?).to be_falsey

expect(NotifyType::FOLLOW.like?).to be_falsey
expect(NotifyType::FOLLOW.comment?).to be_falsey
expect(NotifyType::FOLLOW.follow?).to be_truthy
expect(NotifyType::FOLLOW.mention?).to be_falsey

expect(NotifyType::MENTION.like?).to be_falsey
expect(NotifyType::MENTION.comment?).to be_falsey
expect(NotifyType::MENTION.follow?).to be_falsey
expect(NotifyType::MENTION.mention?).to be_truthy
end
end
end

context "ActiveHash with an enum_accessor set" do
Expand Down

0 comments on commit 22147a3

Please sign in to comment.