Skip to content

Commit

Permalink
Merge pull request #4 from aldinrozario/feature/alt-name-to-ids-metho…
Browse files Browse the repository at this point in the history
…d-for-mapping

Add alt_name_to_ids method for enum value to string mapping
  • Loading branch information
harunkumars authored Jul 5, 2024
2 parents 438287a + b58c26d commit 5ef7213
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
rich_enums (0.1.4)
rich_enums (0.1.5)
activerecord (>= 6.1, < 8.0)

GEM
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ user.role_code # => 'ROLE001'
user.role_for_database # => 1
User.roles # => {"admin"=>1, "user"=>2}
User.role_codes # => {"admin"=>"ROLE001", "user"=>"ROLE101"}
User.role_alt_name_to_ids # => {"ROLE001"=>1, "ROLE101"=>2}

```

Expand Down Expand Up @@ -61,6 +62,7 @@ user.role_alt_name # => 'ROLE001'
user.role_for_database # => 1
User.roles # => {"admin"=>1, "user"=>2}
User.role_alt_names # => {"admin"=>"ROLE001", "user"=>"ROLE101"}
User.role_alt_name_to_ids # => {"ROLE001"=>1, "ROLE101"=>2}
ExternalSystem.sync(user.external_id, role_code: user.role_alt_name)
```
Any arguments other than 'alt' are forwarded to the default enum definition.
Expand Down
25 changes: 19 additions & 6 deletions lib/rich_enums.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ def rich_enum(column_symbol_value_string_options)
# and
# 2. Class method "column1_names" that will map the enum values to the full String description
# and can be accessed by ClassName.<column>_names which will return a hash like { symbol1: string1, symbol2: string2 ...}
# 3. Class method "column1_alt_name_to_ids" will map the enum values the string values and can
# be accessed by ClassName.<column>_alt_name_to_ids which will return a hash like { string1: value1, string2: value2 ...}
# e.g.
# class Enrollment
# include RichEnums
Expand All @@ -31,6 +33,9 @@ def rich_enum(column_symbol_value_string_options)
# Calling learner_payment_path_names returns
# {"greenfig_online"=>"GreenFig Online", "partner"=>"Partner", "partner_online"=>"Partner Online",
# "po_check"=>"P.O. / Check", "other"=>"Other"}
# iii. a class method called learner_payment_path_alt_name_to_ids
# Calling learner_payment_path_alt_name_to_ids returns
# {"GreenFig Online"=>10, "Partner"=>20, "Partner Online"=>30, "P.O. / Check"=>40, "Other"=>100}
# 3. Instance method "column1_name" will return the String associated with the enum value
# e = Enrollment.new
# e.learner_payment_path_po_check! -> normal enum method to update the object with enum value
Expand All @@ -57,21 +62,29 @@ def rich_enum(column_symbol_value_string_options)
options = column_symbol_value_string_options
# we allow for an option called alt: to allow the users to tag the alternate mapping. Defaults to 'alt_name'
alt = options.delete(:alt).to_s || 'alt_name'
alt_map_method = 'alt_name_to_ids'

# create two hashes from the provided input - 1 to be used to define the enum and the other for the name map
split_hash = symbol_value_string.each_with_object({ for_enum: {}, for_display: {} }) do |(symbol, value_string), obj|
obj[:for_enum][symbol] = value_string.is_a?(Array) ? value_string[0] : value_string
obj[:for_display][symbol.to_s] = value_string.is_a?(Array) ? value_string[1] : symbol.to_s
split_hash = symbol_value_string.each_with_object({ for_enum: {}, for_display: {}, for_filter: {} }) do |(symbol, value_string), obj|
value = value_string.is_a?(Array) ? value_string.first : value_string
display_string = value_string.is_a?(Array) ? value_string.second : symbol.to_s

obj[:for_enum][symbol] = value
obj[:for_display][symbol.to_s] = display_string
obj[:for_filter][display_string] = value
end

# 1. Define the Enum
enum "#{column}": split_hash[:for_enum], **options

# 2. Define our custom class method
# - the data to be returned by our custom method is available os a class instance variable
# 2. Define our custom class methods
# - the data to be returned by our custom methods is available as a class instance variable
instance_variable_set("@#{column}_#{alt.pluralize}", split_hash[:for_display])
# - the custom method is just a getter for the class instance variable
instance_variable_set("@#{column}_#{alt_map_method}", split_hash[:for_filter])

# - the custom methods are just a getter for the class instance variables
define_singleton_method("#{column}_#{alt.pluralize}") { instance_variable_get("@#{column}_#{alt.pluralize}") }
define_singleton_method("#{column}_#{alt_map_method}") { instance_variable_get("@#{column}_#{alt_map_method}") }

# 3. Define our custom instance method to show the String associated with the enum value
define_method("#{column}_#{alt}") { self.class.send("#{column}_#{alt.pluralize}")[send(column.to_s)] }
Expand Down
2 changes: 1 addition & 1 deletion lib/rich_enums/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module RichEnums
VERSION = '0.1.4'
VERSION = '0.1.5'
end
24 changes: 24 additions & 0 deletions spec/rich_enums_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,29 @@
expect(test_instance.status_name).to eq("NOT_LIVE")
end
end

context "alternate name to ID mapping" do
let(:test_class) do
Temping.create(:test_class) do
with_columns do |t|
t.integer :status
end

include RichEnums
rich_enum status: {
active: [0, 'LIVE'],
inactive: [1, 'NOT_LIVE']
}, alt: 'name'
end
end

it "returns correct mapping of alternate names to enum values" do
expected_mapping = {
"LIVE" => 0,
"NOT_LIVE" => 1
}
expect(test_class.status_alt_name_to_ids).to eq(expected_mapping)
end
end
end
end

0 comments on commit 5ef7213

Please sign in to comment.