diff --git a/lib/cuprum/collections/association.rb b/lib/cuprum/collections/association.rb index 106abe5..c675e24 100644 --- a/lib/cuprum/collections/association.rb +++ b/lib/cuprum/collections/association.rb @@ -8,14 +8,12 @@ module Cuprum::Collections class Association < Resource # rubocop:disable Metrics/ClassLength # @overload initialize(entity_class: nil, name: nil, qualified_name: nil, singular_name: nil, **options) # @param entity_class [Class, String] the class of entity represented by - # the resource. Aliased as :association_class, :resource_class. + # the resource. # @param inverse [Cuprum::Collections::Resource] the inverse association, # if any. - # @param name [String] the name of the resource. Aliased as - # :association_name, :resource_name. + # @param name [String] the name of the resource. # @param qualified_name [String] a scoped name for the resource. # @param singular_name [String] the name of an entity in the resource. - # Aliased as :singular_resource_name. # @param options [Hash] additional options for the resource. # # @option options foreign_key_name [String] the name of the foreign key @@ -41,12 +39,25 @@ def initialize(**params) super(**params) end - alias association_class entity_class - alias association_name name - # @return [Cuprum::Collections::Resource] the inverse association, if any. attr_reader :inverse + # @return [Class] the class of entity represented by the resource. + def association_class + tools.core_tools.deprecate '#association_class method', + message: 'Use #entity_class instead' + + entity_class + end + + # @return [String] the name of the resource. + def association_name + tools.core_tools.deprecate '#association_name method', + message: 'Use #name instead' + + name + end + # Generates a query for finding matching items. # # @param entities [Array] the entities to query for. diff --git a/lib/cuprum/collections/collection.rb b/lib/cuprum/collections/collection.rb index c46692e..e1feea6 100644 --- a/lib/cuprum/collections/collection.rb +++ b/lib/cuprum/collections/collection.rb @@ -28,11 +28,9 @@ class AbstractCollectionError < StandardError; end # @overload initialize(entity_class: nil, name: nil, qualified_name: nil, singular_name: nil, **options) # @param entity_class [Class, String] the class of entity represented by # the relation. - # @param name [String] the name of the relation. Aliased as - # :collection_name. + # @param name [String] the name of the relation. # @param qualified_name [String] a scoped name for the relation. # @param singular_name [String] the name of an entity in the relation. - # Aliased as :member_name. # @param options [Hash] additional options for the relation. # # @option options primary_key_name [String] the name of the primary key @@ -56,10 +54,6 @@ def initialize(**parameters) # rubocop:disable Metrics/MethodLength @options = ignore_parameters(**parameters) end - alias collection_name name - - alias member_name singular_name - # @return [Hash] additional options for the collection. attr_reader :options @@ -73,6 +67,14 @@ def ==(other) comparable_options == other.comparable_options end + # @return [String] the name of the collection. + def collection_name + tools.core_tools.deprecate '#collection_name method', + message: 'Use #name instead' + + name + end + # @return [Integer] the count of items in the collection. def count query.count @@ -95,6 +97,14 @@ def matches?(**expected) comparable_options >= expected end + # @return [String] the name of an entity in the relation. + def member_name + tools.core_tools.deprecate '#member_name method', + message: 'Use #singular_name instead' + + singular_name + end + # A new Query instance, used for querying against the collection data. # # @return [Object] the query. @@ -118,9 +128,9 @@ def comparable_options def command_options @command_options ||= { - collection_name: collection_name, + collection_name: name, entity_class: entity_class, - member_name: member_name, + member_name: singular_name, primary_key_name: primary_key_name, primary_key_type: primary_key_type, **options @@ -136,5 +146,9 @@ def ignore_parameters(**parameters) def ignored_parameters @ignored_parameters ||= Set.new(IGNORED_PARAMETERS) end + + def tools + SleepingKingStudios::Tools::Toolbelt.instance + end end end diff --git a/lib/cuprum/collections/relation.rb b/lib/cuprum/collections/relation.rb index 713d259..29f9d71 100644 --- a/lib/cuprum/collections/relation.rb +++ b/lib/cuprum/collections/relation.rb @@ -63,14 +63,21 @@ class << self # @param alternatives [Symbol, Array] the additional keywords. # # @return [Hash] the disambiguated keywords. - def disambiguate_keyword(params, key, *alternatives) + def disambiguate_keyword(params, key, *alternatives) # rubocop:disable Metrics/MethodLength params = params.dup values = keyword_values(params, key, *alternatives) return params if values.empty? if values.size == 1 - _, value = values.first + match, value = values.first + + unless match == key + tools.core_tools.deprecate( + "#{match.inspect} keyword", + message: "Use #{key.inspect} instead" + ) + end return params.merge(key => value) end @@ -118,6 +125,10 @@ def keyword_values(keywords, *keys) .map { |key| [key, keywords.delete(key)] } .reject { |_, value| value.nil? } # rubocop:disable Style/CollectionCompact end + + def tools + SleepingKingStudios::Tools::Toolbelt.instance + end end # (see Cuprum::Collections::Relation::Disambiguation.disambiguate_keyword) @@ -382,5 +393,9 @@ def ignore_parameters(**parameters) def ignored_parameters @ignored_parameters ||= Set.new(IGNORED_PARAMETERS) end + + def tools + SleepingKingStudios::Tools::Toolbelt.instance + end end end diff --git a/lib/cuprum/collections/resource.rb b/lib/cuprum/collections/resource.rb index 0390dd4..f17d533 100644 --- a/lib/cuprum/collections/resource.rb +++ b/lib/cuprum/collections/resource.rb @@ -12,12 +12,11 @@ class Resource < Cuprum::Collections::Relation # @overload initialize(entity_class: nil, name: nil, qualified_name: nil, singular_name: nil, **options) # @param entity_class [Class, String] the class of entity represented by - # the resource. Aliased as :resource_class. + # the resource. # @param name [String] the name of the resource. Aliased as # :resource_name. # @param qualified_name [String] a scoped name for the resource. # @param singular_name [String] the name of an entity in the resource. - # Aliased as :singular_resource_name. # @param options [Hash] additional options for the resource. # # @option options plural [Boolean] if true, the resource represents a @@ -39,8 +38,28 @@ def initialize(**params) super(**params) end - alias resource_class entity_class - alias resource_name name - alias singular_resource_name singular_name + # @return [Class] the class of entity represented by the resource. + def resource_class + tools.core_tools.deprecate '#resource_class method', + message: 'Use #entity_class instead' + + entity_class + end + + # @return [String] the name of the resource. + def resource_name + tools.core_tools.deprecate '#resource_name method', + message: 'Use #name instead' + + name + end + + # @return[String] the name of an entity in the resource. + def singular_resource_name + tools.core_tools.deprecate '#singular_resource_name method', + message: 'Use #singular_name instead' + + singular_name + end end end diff --git a/lib/cuprum/collections/rspec/collection_contract.rb b/lib/cuprum/collections/rspec/collection_contract.rb index 0c0aecc..a158055 100644 --- a/lib/cuprum/collections/rspec/collection_contract.rb +++ b/lib/cuprum/collections/rspec/collection_contract.rb @@ -48,6 +48,14 @@ module CollectionContract let(:command) do collection.const_get(class_name).new(**constructor_options) end + let(:expected_options) do + Hash + .new { |_, key| collection.send(key) } + .merge( + collection_name: collection.name, + member_name: collection.singular_name + ) + end it { expect(collection).to define_constant(class_name) } @@ -60,7 +68,7 @@ module CollectionContract command_options.each do |option_name| it "should set the ##{option_name}" do expect(command.send(option_name)) - .to be == collection.send(option_name) + .to be == expected_options[option_name] end end @@ -68,7 +76,7 @@ module CollectionContract let(:constructor_options) do super().merge( custom_option: 'value', - member_name: 'tome' + singular_name: 'tome' ) end @@ -77,9 +85,7 @@ module CollectionContract command_options.each do |option_name| it "should set the ##{option_name}" do expect(command.send(option_name)).to( - be == constructor_options.fetch(option_name) do - collection.send(option_name) - end + be == expected_options[option_name] ) end end @@ -91,6 +97,14 @@ module CollectionContract let(:command) do collection.send(command_name, **constructor_options) end + let(:expected_options) do + Hash + .new { |_, key| collection.send(key) } + .merge( + collection_name: collection.name, + member_name: collection.singular_name + ) + end it 'should define the command' do expect(collection) @@ -104,7 +118,7 @@ module CollectionContract command_options.each do |option_name| it "should set the ##{option_name}" do expect(command.send(option_name)) - .to be == collection.send(option_name) + .to be == expected_options[option_name] end end @@ -112,7 +126,7 @@ module CollectionContract let(:constructor_options) do super().merge( custom_option: 'value', - member_name: 'tome' + singular_name: 'tome' ) end @@ -121,9 +135,7 @@ module CollectionContract command_options.each do |option_name| it "should set the ##{option_name}" do expect(command.send(option_name)).to( - be == constructor_options.fetch(option_name) do - collection.send(option_name) - end + be == expected_options[option_name] ) end end @@ -164,7 +176,7 @@ module CollectionContract include_examples 'should define the command', :validate_one describe '#==' do - let(:other_options) { { collection_name: name } } + let(:other_options) { { name: name } } let(:other_collection) { described_class.new(**other_options) } describe 'with nil' do @@ -198,8 +210,8 @@ module CollectionContract context 'when initialized with options' do let(:constructor_options) do super().merge( - member_name: 'grimoire', - qualified_name: 'spec/scoped_books' + qualified_name: 'spec/scoped_books', + singular_name: 'grimoire' ) end @@ -210,8 +222,8 @@ module CollectionContract describe 'with a collection with matching properties' do let(:other_options) do super().merge( - member_name: 'grimoire', - qualified_name: 'spec/scoped_books' + qualified_name: 'spec/scoped_books', + singular_name: 'grimoire' ) end @@ -299,8 +311,8 @@ def tools describe 'with partially-matching options' do let(:other_options) do { - collection_name: name, - member_name: 'grimoire' + name: name, + singular_name: 'grimoire' } end diff --git a/lib/cuprum/collections/rspec/contracts/relation_contracts.rb b/lib/cuprum/collections/rspec/contracts/relation_contracts.rb index 310257a..afdf412 100644 --- a/lib/cuprum/collections/rspec/contracts/relation_contracts.rb +++ b/lib/cuprum/collections/rspec/contracts/relation_contracts.rb @@ -40,10 +40,27 @@ module ShouldDisambiguateParameter Array(as).each do |alt| describe "##{alt}" do + let(:core_tools) do + SleepingKingStudios::Tools::Toolbelt.instance.core_tools + end + + before(:example) { allow(core_tools).to receive(:deprecate) } + include_examples 'should define reader', alt, -> { subject.send(key) } + it 'should print a deprecation warning' do + subject.send(alt) + + expect(core_tools) + .to have_received(:deprecate) + .with( + "##{alt} method", + message: "Use ##{key} instead" + ) + end + context "when initialized with #{key}: value" do let(:constructor_options) do super().merge(key => value) @@ -74,6 +91,11 @@ module ShouldDisambiguateParameter .tap { |hsh| hsh.delete(key) } .merge(alt => value) end + let(:core_tools) do + SleepingKingStudios::Tools::Toolbelt.instance.core_tools + end + + before(:example) { allow(core_tools).to receive(:deprecate) } it { expect(subject.send(key)).to be == value } end @@ -88,6 +110,11 @@ module ShouldDisambiguateParameter .tap { |hsh| hsh.delete(key) } .merge(alt => value) end + let(:core_tools) do + SleepingKingStudios::Tools::Toolbelt.instance.core_tools + end + + before(:example) { allow(core_tools).to receive(:deprecate) } it { expect(subject.options).not_to have_key alt } end diff --git a/spec/cuprum/collections/basic/collection_spec.rb b/spec/cuprum/collections/basic/collection_spec.rb index 81c6c27..e1d4aaf 100644 --- a/spec/cuprum/collections/basic/collection_spec.rb +++ b/spec/cuprum/collections/basic/collection_spec.rb @@ -33,7 +33,7 @@ expect(described_class) .to respond_to(:new) .with(0).arguments - .and_keywords(:collection_name, :data) + .and_keywords(:data, :entity_class, :name, :qualified_name) .and_any_keywords end end diff --git a/spec/cuprum/collections/basic_spec.rb b/spec/cuprum/collections/basic_spec.rb index 4e827f2..7124e76 100644 --- a/spec/cuprum/collections/basic_spec.rb +++ b/spec/cuprum/collections/basic_spec.rb @@ -4,13 +4,13 @@ RSpec.describe Cuprum::Collections::Basic do describe '.new' do - let(:collection_name) { 'books' } - let(:data) { [] } - let(:options) { { key: 'value' } } + let(:name) { 'books' } + let(:data) { [] } + let(:options) { { key: 'value' } } let(:constructor_options) do { - collection_name: collection_name, - data: data, + name: name, + data: data, **options } end @@ -25,10 +25,10 @@ it { expect(collection).to be_a described_class::Collection } - it { expect(collection.collection_name).to be == collection_name } - it { expect(collection.data).to be == data } + it { expect(collection.name).to be == name } + it { expect(collection.options).to be == options } end end diff --git a/spec/cuprum/collections/relation_spec.rb b/spec/cuprum/collections/relation_spec.rb index 7f9ce96..d2fad42 100644 --- a/spec/cuprum/collections/relation_spec.rb +++ b/spec/cuprum/collections/relation_spec.rb @@ -14,6 +14,13 @@ let(:name) { 'books' } let(:constructor_options) { { name: name } } + let(:core_tools) do + SleepingKingStudios::Tools::Toolbelt.instance.core_tools + end + + before(:example) do + allow(core_tools).to receive(:deprecate) + end describe '::Cardinality' do subject(:relation) { described_class.new(**constructor_options) } @@ -39,7 +46,37 @@ let(:described_class) { super()::Disambiguation } + before(:example) do + allow(core_tools) + .to receive(:deprecate) + .with(an_instance_of(String), message: an_instance_of(String)) + .and_return(nil) + end + describe '.disambiguate_keyword' do + shared_examples 'should not print a deprecation warning' do + it 'should not print a deprecation warning' do + begin + disambiguate + rescue StandardError + # Do nothing. + end + + expect(core_tools).not_to have_received(:deprecate) + end + end + + shared_examples 'should print a deprecation warning' \ + do |actual:, expected:| + it 'should print a deprecation warning' do + disambiguate + + expect(core_tools) + .to have_received(:deprecate) + .with(":#{actual} keyword", message: "Use :#{expected} instead") + end + end + let(:keywords) { {} } let(:key) { :original_key } let(:alternatives) { [] } @@ -60,6 +97,8 @@ def disambiguate it { expect(disambiguate).to be == keywords } + include_examples 'should not print a deprecation warning' + describe 'with keywords' do let(:keywords) do { @@ -69,6 +108,8 @@ def disambiguate end it { expect(disambiguate).to be == keywords } + + include_examples 'should not print a deprecation warning' end end @@ -77,6 +118,8 @@ def disambiguate it { expect(disambiguate).to be == keywords } + include_examples 'should not print a deprecation warning' + describe 'with keywords: no matching keys' do let(:keywords) do { @@ -85,6 +128,8 @@ def disambiguate end it { expect(disambiguate).to be == keywords } + + include_examples 'should not print a deprecation warning' end describe 'with keywords: { original key: value }' do @@ -96,6 +141,8 @@ def disambiguate end it { expect(disambiguate).to be == keywords } + + include_examples 'should not print a deprecation warning' end describe 'with keywords: { alternate key: value }' do @@ -113,6 +160,10 @@ def disambiguate end it { expect(disambiguate).to be == expected } + + include_examples 'should print a deprecation warning', + expected: :original_key, + actual: :alternate_key end describe 'with ambiguous keywords' do @@ -133,6 +184,8 @@ def disambiguate expect { disambiguate } .to raise_error ArgumentError, error_message end + + include_examples 'should not print a deprecation warning' end end @@ -141,6 +194,8 @@ def disambiguate it { expect(disambiguate).to be == keywords } + include_examples 'should not print a deprecation warning' + describe 'with keywords: { original key: value }' do let(:keywords) do { @@ -150,6 +205,8 @@ def disambiguate end it { expect(disambiguate).to be == keywords } + + include_examples 'should not print a deprecation warning' end describe 'with keywords: { alternate key: value }' do @@ -167,6 +224,10 @@ def disambiguate end it { expect(disambiguate).to be == expected } + + include_examples 'should print a deprecation warning', + expected: :original_key, + actual: :alternate_key end describe 'with keywords: { fallback key: value }' do @@ -184,6 +245,10 @@ def disambiguate end it { expect(disambiguate).to be == expected } + + include_examples 'should print a deprecation warning', + expected: :original_key, + actual: :fallback_key end describe 'with ambiguous keywords' do @@ -208,11 +273,36 @@ def disambiguate expect { disambiguate } .to raise_error ArgumentError, error_message end + + include_examples 'should not print a deprecation warning' end end end describe '.resolve_parameters' do + shared_examples 'should not print a deprecation warning' do + it 'should not print a deprecation warning' do + begin + resolved + rescue StandardError + # Do nothing. + end + + expect(core_tools).not_to have_received(:deprecate) + end + end + + shared_examples 'should print a deprecation warning' \ + do |actual:, expected:| + it 'should print a deprecation warning' do + resolved + + expect(core_tools) + .to have_received(:deprecate) + .with(":#{actual} keyword", message: "Use :#{expected} instead") + end + end + let(:parameters) { { name: 'books' } } let(:ambiguous) { {} } let(:resolved) do @@ -245,6 +335,8 @@ def disambiguate .to have_received(:resolve_parameters) .with(parameters) end + + include_examples 'should not print a deprecation warning' end describe 'with one ambiguous keyword' do @@ -260,6 +352,10 @@ def disambiguate .to have_received(:resolve_parameters) .with(received) end + + include_examples 'should print a deprecation warning', + expected: :singular_name, + actual: :member_name end describe 'with many ambiguous keywords' do @@ -292,6 +388,20 @@ def disambiguate .to have_received(:resolve_parameters) .with(received) end + + it 'should print deprecation warnings', :aggregate_failures do # rubocop:disable RSpec/ExampleLength + resolved + + expect(core_tools) + .to have_received(:deprecate) + .with( + ':scoped_name keyword', + message: 'Use :qualified_name instead' + ) + expect(core_tools) + .to have_received(:deprecate) + .with(':member_name keyword', message: 'Use :singular_name instead') + end end end