diff --git a/.rubocop.yml b/.rubocop.yml index 933b2a3..05efcf5 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -8,6 +8,9 @@ AllCops: Rails/ApplicationRecord: Enabled: false +Rails/Output: + Enabled: false + Metrics/ParameterLists: CountKeywordArgs: false diff --git a/Gemfile.lock b/Gemfile.lock index 101aceb..634734d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -22,7 +22,7 @@ GIT PATH remote: . specs: - enum_machine (1.0.0) + enum_machine (2.0.0) activemodel activerecord activesupport @@ -138,7 +138,7 @@ GEM sqlite3 (1.7.3-arm64-darwin) sqlite3 (1.7.3-x86_64-darwin) sqlite3 (1.7.3-x86_64-linux) - timeout (0.4.1) + timeout (0.4.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (3.1.2) diff --git a/README.md b/README.md index 38583ad..eca001f 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ class Product include EnumMachine[color: { enum: %w[red green] }] # or reuse from model - Product::COLOR.decorator_module + Product::COLOR.enum_decorator end Product::COLOR.values # => ["red", "green"] @@ -122,8 +122,8 @@ class Product attr_accessor :color include EnumMachine[color: { - enum: %w[red green], - decorator: ColorDecorator + enum: %w[red green], + value_decorator: ColorDecorator }] end diff --git a/lib/enum_machine.rb b/lib/enum_machine.rb index a5db28c..9ba6215 100644 --- a/lib/enum_machine.rb +++ b/lib/enum_machine.rb @@ -2,9 +2,9 @@ require_relative "enum_machine/version" require_relative "enum_machine/driver_simple_class" -require_relative "enum_machine/build_attribute" +require_relative "enum_machine/build_value_class" require_relative "enum_machine/attribute_persistence_methods" -require_relative "enum_machine/build_class" +require_relative "enum_machine/build_enum_class" require_relative "enum_machine/machine" require "active_support" diff --git a/lib/enum_machine/build_class.rb b/lib/enum_machine/build_enum_class.rb similarity index 98% rename from lib/enum_machine/build_class.rb rename to lib/enum_machine/build_enum_class.rb index fc2667a..ab1c10e 100644 --- a/lib/enum_machine/build_class.rb +++ b/lib/enum_machine/build_enum_class.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module EnumMachine - module BuildClass + module BuildEnumClass def self.call(enum_values:, i18n_scope:, value_class:, machine: nil) aliases = machine&.instance_variable_get(:@aliases) || {} diff --git a/lib/enum_machine/build_attribute.rb b/lib/enum_machine/build_value_class.rb similarity index 92% rename from lib/enum_machine/build_attribute.rb rename to lib/enum_machine/build_value_class.rb index e810a69..99552cd 100644 --- a/lib/enum_machine/build_attribute.rb +++ b/lib/enum_machine/build_value_class.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true module EnumMachine - module BuildAttribute - def self.call(enum_values:, i18n_scope:, decorator:, machine: nil) + module BuildValueClass + def self.call(enum_values:, i18n_scope:, value_decorator:, machine: nil) aliases = machine&.instance_variable_get(:@aliases) || {} Class.new(String) do - include(decorator) if decorator + include(value_decorator) if value_decorator define_method(:machine) { machine } if machine diff --git a/lib/enum_machine/driver_active_record.rb b/lib/enum_machine/driver_active_record.rb index 5368db3..64f9d42 100644 --- a/lib/enum_machine/driver_active_record.rb +++ b/lib/enum_machine/driver_active_record.rb @@ -2,7 +2,7 @@ module EnumMachine module DriverActiveRecord - def enum_machine(attr, enum_values, i18n_scope: nil, decorator: nil, &block) + def enum_machine(attr, enum_values, i18n_scope: nil, value_decorator: nil, &block) klass = self i18n_scope ||= "#{klass.base_class.to_s.underscore}.#{attr}" @@ -11,13 +11,13 @@ def enum_machine(attr, enum_values, i18n_scope: nil, decorator: nil, &block) machine = Machine.new(enum_values, klass, enum_const_name, attr) machine.instance_eval(&block) if block - value_class = BuildAttribute.call(enum_values: enum_values, i18n_scope: i18n_scope, machine: machine, decorator: decorator) - enum_klass = BuildClass.call(enum_values: enum_values, i18n_scope: i18n_scope, machine: machine, value_class: value_class) + value_class = BuildValueClass.call(enum_values: enum_values, i18n_scope: i18n_scope, machine: machine, value_decorator: value_decorator) + enum_class = BuildEnumClass.call(enum_values: enum_values, i18n_scope: i18n_scope, machine: machine, value_class: value_class) value_class.extend(AttributePersistenceMethods[attr, enum_values]) # default_proc for working with custom values not defined in enum list but may exists in db - enum_klass.value_attribute_mapping.default_proc = + enum_class.value_attribute_mapping.default_proc = proc do |hash, enum_value| hash[enum_value] = value_class.new(enum_value).freeze end @@ -102,12 +102,12 @@ def initialize_dup(other) enum_decorator = Module.new do - define_singleton_method(:included) do |decorating_klass| - decorating_klass.prepend define_methods - decorating_klass.const_set enum_const_name, enum_klass + define_singleton_method(:included) do |decorating_class| + decorating_class.prepend define_methods + decorating_class.const_set enum_const_name, enum_class end end - enum_klass.define_singleton_method(:decorator_module) { enum_decorator } + enum_class.define_singleton_method(:enum_decorator) { enum_decorator } klass.include(enum_decorator) diff --git a/lib/enum_machine/driver_simple_class.rb b/lib/enum_machine/driver_simple_class.rb index 6a566c5..538ecd7 100644 --- a/lib/enum_machine/driver_simple_class.rb +++ b/lib/enum_machine/driver_simple_class.rb @@ -11,16 +11,16 @@ def self.call(args) Module.new do define_singleton_method(:included) do |klass| args.each do |attr, params| - enum_values = params.fetch(:enum) - i18n_scope = params.fetch(:i18n_scope, nil) - decorator = params.fetch(:decorator, nil) + enum_values = params.fetch(:enum) + i18n_scope = params.fetch(:i18n_scope, nil) + value_decorator = params.fetch(:value_decorator, nil) if defined?(ActiveRecord) && klass <= ActiveRecord::Base klass.enum_machine(attr, enum_values, i18n_scope: i18n_scope) else enum_const_name = attr.to_s.upcase - value_class = BuildAttribute.call(enum_values: enum_values, i18n_scope: i18n_scope, decorator: decorator) - enum_klass = BuildClass.call(enum_values: enum_values, i18n_scope: i18n_scope, value_class: value_class) + value_class = BuildValueClass.call(enum_values: enum_values, i18n_scope: i18n_scope, value_decorator: value_decorator) + enum_class = BuildEnumClass.call(enum_values: enum_values, i18n_scope: i18n_scope, value_class: value_class) define_methods = Module.new do @@ -28,18 +28,18 @@ def self.call(args) enum_value = super() return unless enum_value - enum_klass.value_attribute_mapping.fetch(enum_value) + enum_class.value_attribute_mapping.fetch(enum_value) end end enum_decorator = Module.new do - define_singleton_method(:included) do |decorating_klass| - decorating_klass.prepend define_methods - decorating_klass.const_set enum_const_name, enum_klass + define_singleton_method(:included) do |decorating_class| + decorating_class.prepend define_methods + decorating_class.const_set enum_const_name, enum_class end end - enum_klass.define_singleton_method(:decorator_module) { enum_decorator } + enum_class.define_singleton_method(:enum_decorator) { enum_decorator } klass.include(enum_decorator) enum_decorator diff --git a/lib/enum_machine/version.rb b/lib/enum_machine/version.rb index 171f209..5ffb13d 100644 --- a/lib/enum_machine/version.rb +++ b/lib/enum_machine/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module EnumMachine - VERSION = "1.0.0" + VERSION = "2.0.0" end diff --git a/spec/enum_machine/active_record_enum_spec.rb b/spec/enum_machine/active_record_enum_spec.rb index 66f8a50..54cd555 100644 --- a/spec/enum_machine/active_record_enum_spec.rb +++ b/spec/enum_machine/active_record_enum_spec.rb @@ -78,8 +78,8 @@ end end - context "when with decorator" do - let(:decorator_module) do + context "when with value_decorator" do + let(:decorator) do Module.new do def am_i_choice? self == "choice" @@ -88,9 +88,9 @@ def am_i_choice? end let(:model_with_decorator) do - decorator = decorator_module + value_decorator = decorator Class.new(TestModel) do - enum_machine :state, %w[choice in_delivery], decorator: decorator + enum_machine :state, %w[choice in_delivery], value_decorator: value_decorator end end @@ -106,6 +106,73 @@ def am_i_choice? end end + describe("#enum_decorator") do + let(:model) do + Class.new(TestModel) do + enum_machine :state, %w[choice in_delivery] + include EnumMachine[color: { enum: %w[red green blue] }] + end + end + + let(:klass) do + Class.new(TestModel) do + enum_machine :state, %w[choice in_delivery] + include EnumMachine[color: { enum: %w[red green blue] }] + end + end + + it "decorates plain class from ar" do + decorating_model = model + decorated_class = + Class.new do + include decorating_model::STATE.enum_decorator + include decorating_model::COLOR.enum_decorator + attr_accessor :state, :color + end + + decorated_item = decorated_class.new + decorated_item.state = "choice" + decorated_item.color = "red" + + expect(decorated_item.state).to be_choice + expect(decorated_item.color).to be_red + expect(decorated_class::STATE::CHOICE).to eq "choice" + expect(decorated_class::COLOR::RED).to eq "red" + end + + it "decorates ar from plain class" do + decorating_class = klass + decorated_model = + Class.new(TestModel) do + include decorating_class::STATE.enum_decorator + include decorating_class::COLOR.enum_decorator + end + + decorated_item = decorated_model.new(state: "choice", color: "red") + + expect(decorated_item.state).to be_choice + expect(decorated_item.color).to be_red + expect(decorated_model::STATE::CHOICE).to eq "choice" + expect(decorated_model::COLOR::RED).to eq "red" + end + + it "decorates ar from ar" do + decorating_model = model + decorated_model = + Class.new(TestModel) do + include decorating_model::STATE.enum_decorator + include decorating_model::COLOR.enum_decorator + end + + decorated_item = decorated_model.new(state: "choice", color: "red") + + expect(decorated_item.state).to be_choice + expect(decorated_item.color).to be_red + expect(decorated_model::STATE::CHOICE).to eq "choice" + expect(decorated_model::COLOR::RED).to eq "red" + end + end + it "serialize model" do Object.const_set(:TestModelSerialize, model) m = TestModelSerialize.create(state: "choice", color: "wrong") @@ -118,30 +185,6 @@ def am_i_choice? expect(unserialized_m.color.red?).to be(false) end - it "test decorator" do - decorating_model = - Class.new(TestModel) do - enum_machine :state, %w[choice in_delivery] - include EnumMachine[color: { enum: %w[red green blue] }] - end - - decorated_klass = - Class.new do - include decorating_model::STATE.decorator_module - include decorating_model::COLOR.decorator_module - attr_accessor :state, :color - end - - decorated_item = decorated_klass.new - decorated_item.state = "choice" - decorated_item.color = "red" - - expect(decorated_item.state).to be_choice - expect(decorated_item.color).to be_red - expect(decorated_klass::STATE::CHOICE).to eq "choice" - expect(decorated_klass::COLOR::RED).to eq "red" - end - it "returns state value by []" do expect(model::STATE["in_delivery"]).to eq "in_delivery" expect(model::STATE["in_delivery"].in_delivery?).to be(true) diff --git a/spec/enum_machine/driver_simple_class_spec.rb b/spec/enum_machine/driver_simple_class_spec.rb index 66a7253..4cfa0fa 100644 --- a/spec/enum_machine/driver_simple_class_spec.rb +++ b/spec/enum_machine/driver_simple_class_spec.rb @@ -10,7 +10,7 @@ def initialize(state) include EnumMachine[state: { enum: %w[choice in_delivery] }] end -module Decorator +module ValueDecorator def am_i_choice? self == "choice" end @@ -23,7 +23,7 @@ def initialize(state) @state = state end - include EnumMachine[state: { enum: %w[choice in_delivery], decorator: Decorator }] + include EnumMachine[state: { enum: %w[choice in_delivery], value_decorator: ValueDecorator }] end RSpec.describe "DriverSimpleClass" do @@ -78,10 +78,10 @@ def initialize(state) expect(TestClass::STATE["wrong"]).to be_nil end - it "#decorator_module" do + it "#enum_decorator" do decorated_klass = Class.new do - include TestClass::STATE.decorator_module + include TestClassWithDecorator::STATE.enum_decorator attr_accessor :state end @@ -127,6 +127,19 @@ def initialize(state) unserialized_m = Marshal.load(Marshal.dump(m)) # rubocop:disable Gp/UnsafeYamlMarshal expect(unserialized_m.state.am_i_choice?).to be(true) end + + it "keeps decorating on #enum_decorator" do + decorated_klass = + Class.new do + include TestClassWithDecorator::STATE.enum_decorator + attr_accessor :state + end + + decorated_item = decorated_klass.new + decorated_item.state = "choice" + + expect(decorated_item.state.am_i_choice?).to be(true) + end end it "serialize class" do