Class: State

Inherits:
ApplicationRecord show all
Defined in:
app/models/state.rb

Overview

== Schema Information

Table name: states
Database name: primary

id :integer not null, primary key
code :string(255) not null
country_iso3 :string(255) not null
name :string(255) not null
region :string

Indexes

index_states_on_code_and_country_iso3 (code,country_iso3) UNIQUE
index_states_on_country_iso3 (country_iso3)

Constant Summary collapse

MAIN_COUNTRIES_ISO3 =
%w[USA CAN]
US_CONTINENTAL_STATE_LIST =
%w[AL AR AZ CA CO CT DC DE FL GA IA ID IL IN KS KY LA MA MD ME MI MN MO MS MT NC ND NE NH NJ NM NV NY OH OK OR PA RI SC
SD TN TX UT VA VT WA WI WV WY]
CA_MAIN_PROVINCES =
%w[AB BC MB NB NS ON QC SK]
CONTINENTAL_REGION_CODES =
[] + US_CONTINENTAL_STATE_LIST + CA_MAIN_PROVINCES

Instance Attribute Summary collapse

Has many collapse

Belongs to collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation

Methods included from Models::EventPublishable

#publish_event

Instance Attribute Details

#codeObject (readonly)



36
# File 'app/models/state.rb', line 36

validates :code, uniqueness: { scope: :country_iso3 }

#country_iso3Object (readonly)



37
# File 'app/models/state.rb', line 37

validates :name, :code, :country_iso3, presence: true

#nameObject (readonly)



37
# File 'app/models/state.rb', line 37

validates :name, :code, :country_iso3, presence: true

Class Method Details

.by_countryActiveRecord::Relation<State>

A relation of States that are by country. Active Record Scope

Returns:

  • (ActiveRecord::Relation<State>)

See Also:



33
# File 'app/models/state.rb', line 33

scope :by_country, ->(country_iso3) { where(country_iso3: country_iso3.upcase) }

.by_country_isoActiveRecord::Relation<State>

A relation of States that are by country iso. Active Record Scope

Returns:

  • (ActiveRecord::Relation<State>)

See Also:



34
# File 'app/models/state.rb', line 34

scope :by_country_iso, ->(country_iso) { joins(:country).where(countries: { iso: country_iso.upcase }) }

.canadaActiveRecord::Relation<State>

A relation of States that are canada. Active Record Scope

Returns:

  • (ActiveRecord::Relation<State>)

See Also:



32
# File 'app/models/state.rb', line 32

scope :canada, -> { where(country_iso3: 'CAN') }

.code_for_string(str, countries_iso3: MAIN_COUNTRIES_ISO3) ⇒ Object

Looks up the state code for the given state name string.
Searches through the given list of country ISO3 codes.
Returns nil if no match found.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'app/models/state.rb', line 118

def self.code_for_string(str, countries_iso3: MAIN_COUNTRIES_ISO3)
  return nil if str.blank?

  subdivision_name = str.strip.upcase
  code = nil
  countries_iso3.each do |iso3|
    next unless (c = ISO3166::Country.find_country_by_alpha3(iso3))

    # This code finder is case sensitive so doing our own
    # code = c.find_subdivision_by_name(str)&.code
    code = c.subdivisions.detect do |sub_code, sub|
      sub_code.upcase == subdivision_name ||
        sub.name.upcase == subdivision_name ||
        [sub.unofficial_names].flatten.compact.any? { |n| n&.upcase == subdivision_name }
    end&.first
    break if code
  end
  # if no matches, try our internal table
  code ||= State.where(country_iso3: countries_iso3).where(State[:name].matches(str, nil, false)).first
  code
end

.options_for_shipping_ratesObject

Returns a list of state name/code pairs for all states except
territories, sorted by region, for use in shipping rate options.



108
109
110
111
112
113
# File 'app/models/state.rb', line 108

def self.options_for_shipping_rates
  # .insert(-1,%w[CONTINENTAL CONTINENTAL])
  where.not(region: 'US - Territories').sort_by(&:region).to_a.map do |c|
    [c.name + ' - ' + c.region.split(' - ').second, c.code]
  end
end

.sortedActiveRecord::Relation<State>

A relation of States that are sorted. Active Record Scope

Returns:

  • (ActiveRecord::Relation<State>)

See Also:



30
# File 'app/models/state.rb', line 30

scope :sorted, -> { order(:name) }

.state_ids_for_select(countries_iso: nil, grouped_by_country: false, locale: nil) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'app/models/state.rb', line 78

def self.state_ids_for_select(countries_iso: nil, grouped_by_country: false, locale: nil)
  locale ||= I18n.locale
  lang_code = locale.to_s.first(2)
  if countries_iso == :all
    grouped_by_country = true # force it otherwise makes no sense
    countries_iso = ISO3166::Country.codes
  elsif countries_iso.nil?
    countries_iso = %w[US CA]
  else
    countries_iso = [countries_iso].flatten.compact
  end
  grouped = {}
  ungrouped = countries_iso.flat_map do |iso|
    iso3166_country = if iso.size == 2
                        ISO3166::Country[iso]
                      elsif iso.size == 3
                        ISO3166::Country.find_country_by_alpha3(iso)
                      end
    next unless iso3166_country

    states_array = iso3166_country.subdivisions.map { |k, v| [v.translations[lang_code] || k, State.where(code: k).first&.id] } || []
    grouped_country_name = iso3166_country.translations[lang_code] || iso3166_country.iso_short_name
    grouped[grouped_country_name] = states_array unless states_array.empty?
    states_array
  end
  grouped_by_country ? grouped : ungrouped
end

.states_for_select(countries_iso: nil, grouped_by_country: false, locale: nil) ⇒ Object

Returns a list of states grouped by country or ungrouped,
filtered by the provided country ISO codes.

countries_iso - An array of country ISO codes to filter states by.
Default is ['US', 'CA']. Pass :all for all countries.
grouped_by_country - Whether to group states by country or return a flat list.
locale - The locale to use for country or state names. Defaults to I18n.locale.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'app/models/state.rb', line 50

def self.states_for_select(countries_iso: nil, grouped_by_country: false, locale: nil)
  locale ||= I18n.locale
  lang_code = locale.to_s.first(2)
  if countries_iso == :all
    grouped_by_country = true # force it otherwise makes no sense
    countries_iso = ISO3166::Country.codes
  elsif countries_iso.nil?
    countries_iso = %w[US CA]
  else
    countries_iso = [countries_iso].flatten.compact
  end
  grouped = {}
  ungrouped = countries_iso.flat_map do |iso|
    iso3166_country = if iso.size == 2
                        ISO3166::Country[iso]
                      elsif iso.size == 3
                        ISO3166::Country.find_country_by_alpha3(iso)
                      end
    next unless iso3166_country

    states_array = iso3166_country.subdivisions.map { |k, v| [v.translations[lang_code] || k, k] } || []
    grouped_country_name = iso3166_country.translations[lang_code] || iso3166_country.iso_short_name
    grouped[grouped_country_name] = states_array unless states_array.empty?
    states_array
  end
  grouped_by_country ? grouped : ungrouped
end

.usaActiveRecord::Relation<State>

A relation of States that are usa. Active Record Scope

Returns:

  • (ActiveRecord::Relation<State>)

See Also:



31
# File 'app/models/state.rb', line 31

scope :usa, -> { where(country_iso3: 'USA') }

Instance Method Details

#countryCountry

Returns:

See Also:



28
# File 'app/models/state.rb', line 28

belongs_to :country, foreign_key: 'country_iso3', primary_key: 'iso3', optional: true

#tax_exemptionsActiveRecord::Relation<TaxExemption>

Returns:

See Also:



25
# File 'app/models/state.rb', line 25

has_many :tax_exemptions, foreign_key: 'state_code', primary_key: 'code'

#tax_ratesActiveRecord::Relation<TaxRate>

Returns:

  • (ActiveRecord::Relation<TaxRate>)

See Also:



26
# File 'app/models/state.rb', line 26

has_many :tax_rates, foreign_key: 'state_code', primary_key: 'code'

#to_sObject



39
40
41
# File 'app/models/state.rb', line 39

def to_s
  name
end