diff --git a/docs/enums.md b/docs/enums.md index faa0fda..06a9ac3 100644 --- a/docs/enums.md +++ b/docs/enums.md @@ -35,3 +35,26 @@ class Review enum :rating, in: { excellent: 100, okay: 50, bad: 25, awful: 10 }, default: :okay end ``` + +You can use the `:_prefix` or `:_suffix` options when you need to define multiple enums with same values. If the passed value is true, the methods are prefixed/suffixed with the name of the enum. It is also possible to supply a custom value: + +```ruby +class Review + include StoreModel::Model + + enum status: [:active, :archived], _suffix: true + enum comments_status: [:active, :inactive], _prefix: :comments +end +``` +With the above example, the predicate methods are now prefixed and/or suffixed accordingly: + +```ruby +review = Review.new(status: :active, comment_status: :inactive) + +review.active_status? # => true +review.archived_status? # => false + +review.comments_active? # => false +review.comments_inactive? # => true + +``` \ No newline at end of file diff --git a/lib/store_model/enum.rb b/lib/store_model/enum.rb index 80270cc..f9c5799 100644 --- a/lib/store_model/enum.rb +++ b/lib/store_model/enum.rb @@ -10,14 +10,15 @@ module Enum # @param kwargs [Object] def enum(name, values = nil, **kwargs) values ||= kwargs[:in] || kwargs + options = kwargs.slice(:_prefix, :_suffix, :default) ensure_hash(values).tap do |mapping| - define_attribute(name, mapping, kwargs[:default]) + define_attribute(name, mapping, options[:default]) define_reader(name, mapping) define_writer(name, mapping) define_method("#{name}_value") { attributes[name.to_s] } define_method("#{name}_values") { mapping } - define_predicate_methods(name, mapping) + define_predicate_methods(name, mapping, options) end end @@ -36,8 +37,9 @@ def define_writer(name, mapping) define_method("#{name}=") { |value| super type.cast_value(value) } end - def define_predicate_methods(name, mapping) + def define_predicate_methods(name, mapping, options) mapping.each do |label, value| + label = affixed_label(label, name, options[:_prefix], options[:_suffix]) define_method("#{label}?") { send(name) == mapping.key(value).to_s } end end @@ -51,5 +53,12 @@ def ensure_hash(values) values.zip(0...values.size).to_h end + + def affixed_label(label, name, prefix = nil, suffix = nil) + prefix = prefix == true ? "#{name}_" : "#{prefix}_" if prefix + suffix = suffix == true ? "_#{name}" : "_#{suffix}" if suffix + + "#{prefix}#{label}#{suffix}" + end end end diff --git a/spec/store_model/enum_spec.rb b/spec/store_model/enum_spec.rb index 8a97459..27c5a80 100644 --- a/spec/store_model/enum_spec.rb +++ b/spec/store_model/enum_spec.rb @@ -108,6 +108,48 @@ end end + context "when multiple enum with prefix is provided" do + let(:config_class) do + Class.new do + include StoreModel::Model + + enum :status, %i[active archived], _prefix: true + enum :comment_status, %i[active archived], _prefix: "comment" + end + end + + subject { config_class.new(status: :active, comment_status: :archived) } + + it "has prefixed predicate methods" do + expect(subject).to be_status_active + expect(subject).not_to be_status_archived + + expect(subject).to be_comment_archived + expect(subject).not_to be_comment_active + end + end + + context "when multiple enum with suffix is provided" do + let(:config_class) do + Class.new do + include StoreModel::Model + + enum :status, %i[active archived], _suffix: true + enum :comment_status, %i[active archived], _suffix: "comment" + end + end + + subject { config_class.new(status: :active, comment_status: :archived) } + + it "has suffixed predicate methods" do + expect(subject).to be_active_status + expect(subject).not_to be_archived_status + + expect(subject).to be_archived_comment + expect(subject).not_to be_active_comment + end + end + describe "#valid?" do let(:config_class) do Class.new do