Class: Spree::Address

Inherits:
Base
  • Object
show all
Extended by:
ActiveModel::ForbiddenAttributesProtection
Defined in:
app/models/spree/address.rb,
app/models/spree/address/name.rb

Overview

Spree::Address provides the foundational ActiveRecord model for recording and validating address information for Spree::Order, Spree::Shipment, Spree::UserAddress, and Spree::Carton.

Defined Under Namespace

Classes: Name, StateValidator

Constant Summary collapse

DB_ONLY_ATTRS =
%w(id updated_at created_at).freeze
TAXATION_ATTRS =
%w(state_id country_id zipcode).freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

display_includes

Methods included from Core::Permalinks

#generate_permalink, #save_permalink

Class Method Details

.build_default(*args, &block) ⇒ Address



44
45
46
# File 'app/models/spree/address.rb', line 44

def self.build_default(*args, &block)
  where(country: Spree::Country.default).build(*args, &block)
end

.factory(attributes) ⇒ Address



49
50
51
52
# File 'app/models/spree/address.rb', line 49

def self.factory(attributes)
  full_attributes = value_attributes(column_defaults, new(attributes).attributes)
  find_or_initialize_by(full_attributes)
end

.immutable_merge(existing_address, new_attributes) ⇒ Address

@note, this may return existing_address if there are no changes to value equality



56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'app/models/spree/address.rb', line 56

def self.immutable_merge(existing_address, new_attributes)
  # Ensure new_attributes is a sanitized hash
  new_attributes = sanitize_for_mass_assignment(new_attributes)

  return factory(new_attributes) if existing_address.nil?

  merged_attributes = value_attributes(existing_address.attributes, new_attributes)
  new_address = factory(merged_attributes)
  if existing_address == new_address
    existing_address
  else
    new_address
  end
end

.value_attributes(base_attributes, merge_attributes = {}) ⇒ Hash



72
73
74
75
# File 'app/models/spree/address.rb', line 72

def self.value_attributes(base_attributes, merge_attributes = {})
  base = base_attributes.stringify_keys.merge(merge_attributes.stringify_keys)
  base.except(*DB_ONLY_ATTRS)
end

Instance Method Details

#==(other_address) ⇒ Boolean

Note:

This compares the addresses based on only the fields that make up the logical “address” and excludes the database specific fields (id, created_at, updated_at).

Returns true if the two addresses have the same address fields.



98
99
100
101
# File 'app/models/spree/address.rb', line 98

def ==(other_address)
  return false unless other_address && other_address.respond_to?(:value_attributes)
  value_attributes == other_address.value_attributes
end

#active_merchant_hashHash



104
105
106
107
108
109
110
111
112
113
114
115
# File 'app/models/spree/address.rb', line 104

def active_merchant_hash
  {
    name:,
    address1:,
    address2:,
    city:,
    state: state_text,
    zip: zipcode,
    country: country.try(:iso),
    phone:
  }
end

#country_isoObject



144
145
146
# File 'app/models/spree/address.rb', line 144

def country_iso
  country && country.iso
end

#country_iso=(iso) ⇒ Country

Returns setter that sets self.country to the Country with a matching 2 letter iso.

Raises:

  • (ActiveRecord::RecordNotFound)

    if country with the iso doesn’t exist



140
141
142
# File 'app/models/spree/address.rb', line 140

def country_iso=(iso)
  self.country = Spree::Country.find_by!(iso:)
end

#readonly?Boolean

This is set in order to preserve immutability of Addresses. Use #dup to create new records as required, but it probably won’t be required as often as you think. Since addresses do not change, you won’t accidentally alter historical data.



133
134
135
# File 'app/models/spree/address.rb', line 133

def readonly?
  persisted?
end

#require_phone?true



120
121
122
# File 'app/models/spree/address.rb', line 120

def require_phone?
  Spree::Config[:address_requires_phone]
end

#require_zipcode?true



126
127
128
# File 'app/models/spree/address.rb', line 126

def require_zipcode?
  true
end

#state_textString



87
88
89
# File 'app/models/spree/address.rb', line 87

def state_text
  state.try(:abbr) || state.try(:name) || state_name
end

#taxation_attributesObject



82
83
84
# File 'app/models/spree/address.rb', line 82

def taxation_attributes
  self.class.value_attributes(attributes.slice(*TAXATION_ATTRS))
end

#to_sObject



91
92
93
# File 'app/models/spree/address.rb', line 91

def to_s
  "#{name}: #{address1}"
end

#value_attributesHash



78
79
80
# File 'app/models/spree/address.rb', line 78

def value_attributes
  self.class.value_attributes(attributes)
end