diff --git a/Gemfile.lock b/Gemfile.lock index 65db761..4f68183 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - enumbler (0.6.0) + enumbler (0.6.1) activerecord (>= 5.2.3, < 6.1) activesupport (>= 5.2.3, < 6.1) diff --git a/README.md b/README.md index 02b1a51..1411da2 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Suppose you have a `House` and you want to add some `colors` to the house. You ActiveRecord::Schema.define do create_table :colors|t| t.string :label, null: false, index: { unique: true } + t.string :hex, null: true end create_table :houses|t| @@ -42,8 +43,8 @@ end class Color < ApplicationRecord include Enumbler::Enabler - enumble :black, 1 - enumble :white, 2 + enumble :black, 1, hex: '000000' + enumble :white, 2, hex: 'ffffff' enumble :dark_brown, 3 enumble :infinity, 4, label: 'Infinity - and beyond!' end diff --git a/lib/enumbler/enabler.rb b/lib/enumbler/enabler.rb index d04c8a9..7b42263 100644 --- a/lib/enumbler/enabler.rb +++ b/lib/enumbler/enabler.rb @@ -40,8 +40,8 @@ module ClassMethods # class Color < ApplicationRecord # include Enumbler::Enabler # - # enumble :black, 1 - # enumble :white, 2 + # enumble :black, 1, hex: '000000' + # enumble :white, 2, hex: 'ffffff' # enumble :dark_brown, 3, # label: 'dark-brown' # enumble :black_hole, 3, label: 'Oh my! It is a black hole!' # end @@ -55,14 +55,16 @@ module ClassMethods # @param enum [Symbol] the enum representation # @param id [Integer] the primary key value # @param label [String] optional: label for humans - # @param **options [Hash] optional: additional attributes and values that + # @param **attributes [Hash] optional: additional attributes and values that # will be saved to the database for this enumble record - def enumble(enum, id, label: nil, **options) + def enumble(enum, id, label: nil, **attributes) @enumbles ||= Enumbler::Collection.new @enumbled_model = self @enumbler_label_column_name ||= :label - enumble = Enumble.new(enum, id, label: label, label_column_name: @enumbler_label_column_name, **options) + raise_error_if_model_does_not_support_attributes(attributes) + + enumble = Enumble.new(enum, id, label: label, label_column_name: @enumbler_label_column_name, **attributes) if @enumbles.include?(enumble) raise Error, "You cannot add the same Enumble twice! Attempted to add: #{enum}, #{id}." @@ -310,6 +312,17 @@ def define_dynamic_methods_and_constants_for_enumbled_model(enumble) raise Enumbler::Error, "The attribute #{attr} is not supported on this Enumble." end end + + def raise_error_if_model_does_not_support_attributes(attributes) + return if attributes.blank? + + unsupported_attrs = attributes.reject { |key, _value| has_attribute?(key) } + + return if unsupported_attrs.blank? + + raise Enumbler::Error, + "The model #{self} does not support the attribute(s): #{unsupported_attrs.keys.map(&:to_s).to_sentence}" + end end end end diff --git a/lib/enumbler/enumble.rb b/lib/enumbler/enumble.rb index 307c12f..075f7ba 100644 --- a/lib/enumbler/enumble.rb +++ b/lib/enumbler/enumble.rb @@ -2,18 +2,15 @@ module Enumbler # Class that holds each row of Enumble data. - # - # @todo We need to support additional options/attributes beyond the id/label - # pairs. Is on the backburner for a moment. class Enumble - attr_reader :id, :enum, :label, :label_column_name, :options + attr_reader :id, :enum, :label, :label_column_name - def initialize(enum, id, label: nil, label_column_name: :label, **options) + def initialize(enum, id, label: nil, label_column_name: :label, **attributes) @id = id @enum = enum @label = label || enum.to_s.dasherize @label_column_name = label_column_name - @options = options + @additional_attributes = attributes || {} end def ==(other) @@ -22,10 +19,10 @@ def ==(other) end def attributes - { + @additional_attributes.merge({ id: id, label_column_name => label, - } + }) end # Used to return itself from a class method. diff --git a/lib/enumbler/version.rb b/lib/enumbler/version.rb index f22161f..96d9198 100644 --- a/lib/enumbler/version.rb +++ b/lib/enumbler/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Enumbler - VERSION = '0.6.0' + VERSION = '0.6.1' end diff --git a/spec/enumbler_spec.rb b/spec/enumbler_spec.rb index a5ced24..c41eec7 100644 --- a/spec/enumbler_spec.rb +++ b/spec/enumbler_spec.rb @@ -6,6 +6,7 @@ ActiveRecord::Schema.define do create_table :colors, force: true do |t| t.string :label, null: false, index: { unique: true } + t.string :hex, null: true end create_table :feelings, force: true do |t| @@ -29,8 +30,8 @@ class Color < ApplicationRecord # @!parse extend Enumbler::Enabler::ClassMethods include Enumbler::Enabler - enumble :black, 1 - enumble :white, 2 + enumble :black, 1, hex: '000000' + enumble :white, 2, hex: 'ffffff' enumble :dark_brown, 3 enumble :infinity, 4, label: 'This is a made-up color' end @@ -82,6 +83,11 @@ class House < ApplicationRecord it 'creates the class finder methods', :seed do expect(Color.black).to eq Color.find(Color::BLACK) end + + it 'raises an error when attempting to add an attribute that is not supported' do + expect { Color.enumble(:pink, 8, bob: 'the builder') }.to raise_error(Enumbler::Error, /not support/) + end + it 'creates the query methods', :seed do expect(Color.black).to be_black expect(Color.black.is_black).to be true @@ -238,6 +244,12 @@ class House < ApplicationRecord it 'uses a custom label' do expect(Color.infinity.label).to eq 'This is a made-up color' end + + it 'includes additional attributes' do + expect(Color.black.hex).to eq '000000' + expect(Color.white.hex).to eq 'ffffff' + end + it 'updates the records' do Color.enumble :pink, 8