Class: Spree::Zone

Inherits:
Object
  • Object
show all
Includes:
UniqueName
Defined in:
app/models/spree/zone.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.default_taxObject



29
30
31
# File 'app/models/spree/zone.rb', line 29

def self.default_tax
  Spree::Current.default_tax_zone
end

.match(address_or_country) ⇒ Object

Returns the matching zone with the highest priority zone type (State, Country, Zone.) Returns nil in the case of no matches. Accepts either an address (with country_id/state_id) or a Spree::Country directly.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'app/models/spree/zone.rb', line 56

def self.match(address_or_country)
  return unless address_or_country

  if address_or_country.is_a?(Spree::Country)
    country_id = address_or_country.id
    state_id = nil
  else
    country_id = address_or_country.country_id
    state_id = address_or_country.state_id
  end

  matches = includes(:zone_members).
              order('spree_zones.zone_members_count', 'spree_zones.created_at').
              where("(spree_zone_members.zoneable_type = 'Spree::Country' AND " \
                    'spree_zone_members.zoneable_id = ?) OR ' \
                    "(spree_zone_members.zoneable_type = 'Spree::State' AND " \
                    'spree_zone_members.zoneable_id = ?)', country_id, state_id).
              references(:zones)

  return if matches.empty?

  %w[state country].each do |zone_kind|
    if match = matches.detect { |zone| zone_kind == zone.kind }
      return match
    end
  end
  matches.first
end

.potential_matching_zones(zone) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/models/spree/zone.rb', line 33

def self.potential_matching_zones(zone)
  if zone.country?
    # Match zones of the same kind with similar countries
    joins(countries: :zones).
      where('zone_members_spree_countries_join.zone_id = ?', zone.id).
      distinct
  else
    # Match zones of the same kind with similar states in AND match zones
    # that have the states countries in
    joins(:zone_members).where(
      "(spree_zone_members.zoneable_type = 'Spree::State' AND
        spree_zone_members.zoneable_id IN (?))
       OR (spree_zone_members.zoneable_type = 'Spree::Country' AND
        spree_zone_members.zoneable_id IN (?))",
      zone.state_ids,
      zone.states.pluck(:country_id)
    ).distinct
  end
end

Instance Method Details

#<=>(other) ⇒ Object



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

def <=>(other)
  name <=> other.name
end

#contains?(target) ⇒ Boolean

Indicates whether the specified zone falls entirely within the zone performing the check.

Returns:

  • (Boolean)


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'app/models/spree/zone.rb', line 162

def contains?(target)
  return false if state? && target.country?
  return false if zone_members.empty? || target.zone_members.empty?

  if kind == target.kind
    if state?
      return false if (target.states.pluck(:id) - states.pluck(:id)).present?
    elsif country?
      return false if (target.countries.pluck(:id) - countries.pluck(:id)).present?
    end
  else
    return false if (target.states.pluck(:country_id) - countries.pluck(:id)).present?
  end
  true
end

#country?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'app/models/spree/zone.rb', line 95

def country?
  kind == 'country'
end

#country_idsObject



136
137
138
139
140
141
142
# File 'app/models/spree/zone.rb', line 136

def country_ids
  if country?
    members.pluck(:zoneable_id)
  else
    []
  end
end

#country_ids=(ids) ⇒ Object



152
153
154
# File 'app/models/spree/zone.rb', line 152

def country_ids=(ids)
  set_zone_members(ids, 'Spree::Country')
end

#country_listObject

convenience method for returning the countries contained within a zone



117
118
119
120
121
122
123
124
# File 'app/models/spree/zone.rb', line 117

def country_list
  @countries ||= case kind
                 when 'country' then
                   Country.where(id: country_ids)
                 when 'state' then
                   Country.where(id: zoneables.collect(&:country_id))
                 end
end

#include?(address) ⇒ Boolean

Returns:

  • (Boolean)


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

def include?(address)
  return false unless address

  members.any? do |zone_member|
    case zone_member.zoneable_type
    when 'Spree::Country'
      zone_member.zoneable_id == address.country_id
    when 'Spree::State'
      zone_member.zoneable_id == address.state_id
    end
  end
end

#kindObject



85
86
87
88
89
90
91
92
93
# File 'app/models/spree/zone.rb', line 85

def kind
  if self[:kind].present?
    self[:kind]
  else
    not_nil_scope = members.where.not(zoneable_type: nil)
    zone_type = not_nil_scope.order('created_at ASC').pluck(:zoneable_type).last
    zone_type&.demodulize&.underscore
  end
end

#state?Boolean

Returns:

  • (Boolean)


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

def state?
  kind == 'state'
end

#state_idsObject



144
145
146
147
148
149
150
# File 'app/models/spree/zone.rb', line 144

def state_ids
  if state?
    members.pluck(:zoneable_id)
  else
    []
  end
end

#state_ids=(ids) ⇒ Object



156
157
158
# File 'app/models/spree/zone.rb', line 156

def state_ids=(ids)
  set_zone_members(ids, 'Spree::State')
end

#state_listObject



178
179
180
181
182
183
184
185
# File 'app/models/spree/zone.rb', line 178

def state_list
  case kind
  when 'country'
    zoneables.map(&:states)
  when 'state'
    zoneables
  end.flatten.compact.uniq
end

#state_list_for(country) ⇒ Object



187
188
189
# File 'app/models/spree/zone.rb', line 187

def state_list_for(country)
  state_list.select { |state| state.country == country }
end

#zoneablesObject

All zoneables belonging to the zone members. Will be a collection of either countries or states depending on the zone type.



132
133
134
# File 'app/models/spree/zone.rb', line 132

def zoneables
  members.includes(:zoneable).collect(&:zoneable)
end