dblock / ruby-enum Goto Github PK
View Code? Open in Web Editor NEWA handy way to define enums in Ruby.
License: MIT License
A handy way to define enums in Ruby.
License: MIT License
Ruby version: ruby 2.5.5p157 (2019-03-15 revision 67260) [x86_64-linux-musl]
ruby-enum version: 0.7.2
While building ruby-enum for Alpine Linux, the suite reports the following errors:
rspec ./spec/ruby-enum/enum_spec.rb:23 # Ruby::Enum raises UninitializedConstantError on an invalid constant
rspec ./spec/ruby-enum/enum_spec.rb:122 # Ruby::Enum on duplicate keys raises DuplicateKeyError
rspec ./spec/ruby-enum/enum_spec.rb:132 # Ruby::Enum on duplicate values raises a DuplicateValueError
rspec ./spec/ruby-enum/enum_spec.rb:145 # Ruby::Enum Given a class that has not defined any enums should raise Ruby::Enum::Errors::UninitializedConstantError
rspec ./spec/ruby-enum/enum_spec.rb:167 # Ruby::Enum Subclass behavior parent class should not have enums defined in child classes
See https://gist.github.com/Ikke/e9690849306977865e9df9f8598886a2 for the exceptions.
This might be due to the Ruby-i18n upgrade.
Lets do a release after #14 is merged. Maybe 0.7.0 since #3 is a pretty big piece of functionality.
@laertispappas care to follow https://github.com/dblock/ruby-enum/blob/master/RELEASING.md then?
Travis-ci is trouble these days, replace with GH actions.
@dblock Thanks for making this gem! :)
One use case I have for enums is that I want to use them in case statements. A nice feature in Rust is exhaustive matching. Obviously, this doesn't work in native Ruby because of the missing types. However, in ruby-enum, it can work, because we have the information about which cases should be handled.
A possible drawback of this is that such a check adds additional steps to each call of the case statement and makes the runtime of the code slower.
I implemented a quick version of this in a project of mine and would be happy to contribute it to this project. A default/else block could be added as well.
Let me know what you think about it :)
##
# Adds a method to an enum class that allows for exhaustive matching on a value.
#
# @example
# class Color
# include Ruby::Enum
# include Ruby::Enum::Ecase
#
# define :RED, :red
# define :GREEN, :green
# define :BLUE, :blue
# end
#
# Color.ecase(Color::RED, {
# [Color::RED, Color::GREEN] => -> { puts "red or green" },
# Color::BLUE => -> { puts "blue" },
# })
module Ruby::Enum::Ecase
def self.included(klass)
klass.extend(ClassMethods)
end
##
# @see Ruby::Enum::Ecase
module ClassMethods
class ValuesNotDefinedError < StandardError
end
class NotAllCasesHandledError < StandardError
end
def ecase(value, cases)
validate_cases(cases)
cases.each do |values, block|
values = [values] unless values.is_a?(Array)
block.call if values.include?(value)
end
end
private
def validate_cases(cases)
all_values = cases.keys.flatten
superfluous_values = all_values - values
missing_values = values - all_values
if superfluous_values.any?
raise ValuesNotDefinedError, "Value(s) not defined: #{superfluous_values.join(", ")}"
end
if missing_values.any? # rubocop:disable Style/GuardClause
raise NotAllCasesHandledError, "Not all cases handled: #{missing_values.join(", ")}"
end
end
end
end
Add 3.0 ruby, make sure we're compatible
From the documentation ("Attempts to parse an enumerated value"), I've been assuming the parse()
method takes a value and returns the enum instance. I only discovered it didn't when I tried to use it with CONSTANT_CASE keys and CamelCase values:
require 'ruby-enum'
class Example
include Ruby::Enum
define :FOO, 'Foo'
define :BAR, 'Bar'
define :BAZ_QUX, 'BazQux'
define :CORGE_GRAUPLY, 'CorgeGrauply'
end
Example.values.each do |v|
parsed = Example.parse(v)
puts "#{v} : #{parsed}"
end
# => Foo : Foo
# => Bar : Bar
# => BazQux :
# => CorgeGrauply :
I've created two patches, one that clarifies the documentation, and another that adds a method for_value()
that does what I thought parse()
did, as well as a corresponding for_key()
. See what you think.
Allow define
to optionally accept a value.
If no value is given, the value will default to the key:
class A
include Ruby::Enum
define :X
end
A::X == :X
@dblock Please push version 0.7.2 to RubyGems.
The values
class method does not inherit the defined enum values from the parent class.
class A
include Ruby::Enum
define :X, 'X'
end
class B < A
include Ruby::Enum
define :Y, 'Y'
end
I would expect:
B.values() == [B::X, B::Y]
yet
B.values() == [B::Y]
if it's supported: add some tests for it; if not: raise an error when trying to subclass, or when trying to call .define
from the subclass
Coming from gjtorikian/commonmarker#135, the i18n dependency brings in concurrent-ruby, which seems like unnecessary for many scenarios. Make it optional.
Looks like https://github.com/dblock/ruby-enum/actions/runs/7441263339/job/20243173198 failed.
Given a Gemfile like:
source 'https://rubygems.org/'
gem 'ruby-enum', '0.7.1'
gem 'rake'
And a Rakefile like:
task :go do
require 'ruby-enum'
class Parse
include Ruby::Enum
define :default, 0
define :normalize, (1 << 8)
define :validate_utf8, (1 << 9)
define :smart, (1 << 10)
end
puts Parse.to_h[:smart]
end
Running rake go
bombs on 0.7.1:
rake aborted!
NameError: wrong constant name default
/Users/gjtorikian/Desktop/foo/Rakefile:7:in `<class:Parse>'
/Users/gjtorikian/Desktop/foo/Rakefile:4:in `block in <top (required)>'
/Users/gjtorikian/.rbenv/versions/2.2.3/bin/bundle:23:in `load'
/Users/gjtorikian/.rbenv/versions/2.2.3/bin/bundle:23:in `<main>'
Tasks: TOP => go
(See full trace by running task with --trace)
Versions 0.7.0 and lower worked as expected, though.
Hi,
this operator requires ruby 2.3.0
ruby-enum/lib/ruby-enum/enum.rb
Line 90 in c6a2e67
Using ruby 2.1.7 fails with an "unexpected error"
/home/.rvm/gems/ruby-2.1.7/gems/ruby-enum-0.8.0/lib/ruby-enum.rb:6:in 'require': /home/.rvm/gems/ruby-2.1.7/gems/ruby-enum-0.8.0/lib/ruby-enum/enum.rb:90: syntax error, unexpected '.' (SyntaxError)
enum&.value
^
/home/.rvm/gems/ruby-2.1.7/gems/ruby-enum-0.8.0/lib/ruby-enum/enum.rb:111: syntax error, unexpected '.'
enum&.key
^
from /home/.rvm/gems/ruby-2.1.7/gems/ruby-enum-0.8.0/lib/ruby-enum.rb:6:in '<top (required)>'```
Add a section about what's different between Ruby::Enum and https://github.com/dmolesUC3/typesafe_enum, cc: @dmolesUC3
Add
danger-changelog
danger-toc
While I'll admit it's a bit pedantic to zero in on such a minor aspect of the gem specification, I think it's important to minimize friction and implicit dependencies wherever possible in packages we write for other developers.
While it's very unlikely that a dev using Ruby isn't also using git, I think it's good practice to make as few assumptions
about a user's development environment as possible.
Here's the code in context:
https://github.com/dblock/ruby-enum/blob/master/ruby-enum.gemspec#L11
and here's my suggested change. I think it's a bit naïve, but I think it's is a step in the right direction:
s.files = `git ls-files`.split("\n")
s.files = Dir['*']
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.