diff --git a/core/app/models/spree/address.rb b/core/app/models/spree/address.rb index 69927794fe2..34af690a790 100644 --- a/core/app/models/spree/address.rb +++ b/core/app/models/spree/address.rb @@ -193,7 +193,7 @@ def state_validate # ensure state_name belongs to country without states, or that it matches a predefined state name/abbr if state_name.present? if country.states.present? - states = country.states.find_all_by_name_or_abbr(state_name) + states = country.states.with_name_or_abbr(state_name) if states.size == 1 self.state = states.first diff --git a/core/app/models/spree/state.rb b/core/app/models/spree/state.rb index 384b4f20a72..aed1b3967a5 100644 --- a/core/app/models/spree/state.rb +++ b/core/app/models/spree/state.rb @@ -5,8 +5,16 @@ class State < Spree::Base validates :country, :name, presence: true - def self.find_all_by_name_or_abbr(name_or_abbr) - where('name = ? OR abbr = ?', name_or_abbr, name_or_abbr) + scope :with_name_or_abbr, ->(name_or_abbr) do + where( + arel_table[:name].matches(name_or_abbr).or( + arel_table[:abbr].matches(name_or_abbr) + ) + ) + end + class << self + alias_method :find_all_by_name_or_abbr, :with_name_or_abbr + deprecate find_all_by_name_or_abbr: :with_name_or_abbr, deprecator: Spree::Deprecation end # table of { country.id => [ state.id , state.name ] }, arrays sorted by name diff --git a/core/spec/models/spree/address_spec.rb b/core/spec/models/spree/address_spec.rb index e274821557f..c562966d9ab 100644 --- a/core/spec/models/spree/address_spec.rb +++ b/core/spec/models/spree/address_spec.rb @@ -21,7 +21,7 @@ let(:address) { build(:address, country: country) } before do - allow(country.states).to receive_messages find_all_by_name_or_abbr: [state] + allow(country.states).to receive_messages with_name_or_abbr: [state] end context 'address does not require state' do diff --git a/core/spec/models/spree/state_spec.rb b/core/spec/models/spree/state_spec.rb index 42c9eb552d3..664e9463d47 100644 --- a/core/spec/models/spree/state_spec.rb +++ b/core/spec/models/spree/state_spec.rb @@ -1,10 +1,37 @@ require 'spec_helper' describe Spree::State, type: :model do - it "can find a state by name or abbr" do - state = create(:state, name: "California", abbr: "CA") - expect(Spree::State.find_all_by_name_or_abbr("California")).to include(state) - expect(Spree::State.find_all_by_name_or_abbr("CA")).to include(state) + describe '.with_name_or_abbr' do + subject do + Spree::State.with_name_or_abbr(search_term) + end + + let!(:state) { create(:state, name: "California", abbr: "CA") } + + context 'by invalid term' do + let(:search_term) { 'NonExistent' } + it { is_expected.to be_empty } + end + + context 'by name' do + let(:search_term) { 'California' } + it { is_expected.to include(state) } + end + + context 'by abbr' do + let(:search_term) { 'CA' } + it { is_expected.to include(state) } + end + + context 'by case-insensitive abbr' do + let(:search_term) { 'CaLiFoRnIa' } + it { is_expected.to include(state) } + end + + context 'by case-insensitive abbr' do + let(:search_term) { 'cA' } + it { is_expected.to include(state) } + end end it "can find all states group by country id" do