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)
TAXATION_ATTRS =
%w(state_id country_id zipcode)
LEGACY_NAME_ATTRS =
%w(firstname lastname full_name)

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

display_includes, #initialize_preference_defaults, page, preference

Methods included from Core::Permalinks

#generate_permalink, #save_permalink

Methods included from Preferences::Preferable

#admin_form_preference_names, #default_preferences, #defined_preferences, #get_preference, #has_preference!, #has_preference?, #preference_default, #preference_type, #set_preference

Class Method Details

.build_default(*args, &block) ⇒ Address



57
58
59
# File 'app/models/spree/address.rb', line 57

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

.factory(attributes) ⇒ Address



62
63
64
65
# File 'app/models/spree/address.rb', line 62

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



69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'app/models/spree/address.rb', line 69

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



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'app/models/spree/address.rb', line 85

def self.value_attributes(base_attributes, merge_attributes = {})
  base = base_attributes.stringify_keys.merge(merge_attributes.stringify_keys)

  name_from_attributes = Spree::Address::Name.from_attributes(base)
  if base['firstname'].presence || base['first_name'].presence
    base['firstname'] = name_from_attributes.first_name
  end
  if base['lastname'].presence || base['last_name'].presence
    base['lastname'] = name_from_attributes.last_name
  end
  excluded_attributes = DB_ONLY_ATTRS + %w(first_name last_name)

  base.except(*excluded_attributes)
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.



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

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

#active_merchant_hashHash



152
153
154
155
156
157
158
159
160
161
162
163
# File 'app/models/spree/address.rb', line 152

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

#as_json(options = {}) ⇒ Object



212
213
214
215
216
217
218
219
220
# File 'app/models/spree/address.rb', line 212

def as_json(options = {})
  if Spree::Config.use_combined_first_and_last_name_in_address
    super(options.merge(except: LEGACY_NAME_ATTRS)).tap do |hash|
      hash['name'] = name
    end
  else
    super
  end
end

#blank?Boolean

This exists because the default Object#blank?, checks empty? if it is defined, and we have defined empty. This should be removed once empty? is removed



147
148
149
# File 'app/models/spree/address.rb', line 147

def blank?
  false
end

#country_isoObject



192
193
194
# File 'app/models/spree/address.rb', line 192

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



188
189
190
# File 'app/models/spree/address.rb', line 188

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

#empty?Boolean

Deprecated.

Do not use this



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

def empty?
  Spree::Deprecation.warn("Address#empty? is deprecated.", caller)
  attributes.except('id', 'created_at', 'updated_at', 'country_id').all? { |_, value| value.nil? }
end

#nameString



197
198
199
200
201
202
# File 'app/models/spree/address.rb', line 197

def name
  Spree::Address::Name.new(
    read_attribute(:firstname),
    read_attribute(:lastname)
  ).value
end

#name=(value) ⇒ Object



204
205
206
207
208
209
210
# File 'app/models/spree/address.rb', line 204

def name=(value)
  return if value.nil?

  name_from_value = Spree::Address::Name.new(value)
  write_attribute(:firstname, name_from_value.first_name)
  write_attribute(:lastname, name_from_value.last_name)
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.



181
182
183
# File 'app/models/spree/address.rb', line 181

def readonly?
  persisted?
end

#require_phone?true



168
169
170
# File 'app/models/spree/address.rb', line 168

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

#require_zipcode?true



174
175
176
# File 'app/models/spree/address.rb', line 174

def require_zipcode?
  true
end

#same_as(other_address) ⇒ Object

Deprecated.

Do not use this. Use Address.== instead.



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

def same_as(other_address)
  Spree::Deprecation.warn("Address#same_as is deprecated. It's equivalent to Address.==", caller)
  self == other_address
end

#same_as?(other_address) ⇒ Boolean

Deprecated.

Do not use this. Use Address.== instead.



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

def same_as?(other_address)
  Spree::Deprecation.warn("Address#same_as? is deprecated. It's equivalent to Address.==", caller)
  self == other_address
end

#state_textString



110
111
112
# File 'app/models/spree/address.rb', line 110

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

#taxation_attributesObject



105
106
107
# File 'app/models/spree/address.rb', line 105

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

#to_sObject



114
115
116
# File 'app/models/spree/address.rb', line 114

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

#value_attributesHash



101
102
103
# File 'app/models/spree/address.rb', line 101

def value_attributes
  self.class.value_attributes(attributes)
end