Class: Spree::Taxon

Inherits:
Object
  • Object
show all
Extended by:
FriendlyId
Includes:
PgSearch::Model, MemoizedData, Metadata, TranslatableResource, TranslatableResourceSlug, Webhooks::HasWebhooks
Defined in:
app/models/spree/taxon.rb

Constant Summary collapse

RULES_MATCH_POLICIES =
%w[all any].freeze
SORT_ORDERS =
%w[
  manual
  best-selling
  name-a-z
  name-z-a
  price-high-to-low
  price-low-to-high
  newest-first
  oldest-first
]
MEMOIZED_METHODS =
%w[cached_self_and_descendants_ids].freeze
TRANSLATABLE_FIELDS =

Translations

i[name pretty_name description permalink].freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.search_by_name(query) ⇒ Object



116
117
118
# File 'app/models/spree/taxon.rb', line 116

def self.search_by_name(query)
  i18n { name.lower.matches("%#{query.downcase}%") }
end

Instance Method Details

#active_productsObject



357
358
359
# File 'app/models/spree/taxon.rb', line 357

def active_products
  products.active
end

#active_products_with_descendantsObject



164
165
166
167
168
169
170
171
172
173
# File 'app/models/spree/taxon.rb', line 164

def active_products_with_descendants
  @active_products_with_descendants ||= store.products.
                                        joins(:classifications).
                                        active.
                                        where(
                                          Spree::Classification.table_name => {
                                            taxon_id: descendants.ids + [id]
                                          }
                                        )
end

#applicable_filtersObject

indicate which filters should be used for a taxon this method should be customized to your own site



316
317
318
319
320
321
322
323
324
# File 'app/models/spree/taxon.rb', line 316

def applicable_filters
  fs = []
  # fs << ProductFilters.taxons_below(self)
  ## unless it's a root taxon? left open for demo purposes

  fs << Spree::Core::ProductFilters.price_filter if Spree::Core::ProductFilters.respond_to?(:price_filter)
  fs << Spree::Core::ProductFilters.brand_filter if Spree::Core::ProductFilters.respond_to?(:brand_filter)
  fs
end

#cached_self_and_descendants_idsObject



377
378
379
380
381
# File 'app/models/spree/taxon.rb', line 377

def cached_self_and_descendants_ids
  @cached_self_and_descendants_ids ||= Rails.cache.fetch("#{cache_key_with_version}/descendant-ids") do
    self_and_descendants.ids
  end
end

#child_index=(idx) ⇒ Object

awesome_nested_set sorts by :lft and :rgt. This call re-inserts the child node so that its resulting position matches the observable 0-indexed position. ** Note ** no :position column needed - a_n_s doesn’t handle the reordering if

you bring your own :order_column.

See #3390 for background.


389
390
391
# File 'app/models/spree/taxon.rb', line 389

def child_index=(idx)
  move_to_child_with_index(parent, idx.to_i) unless new_record?
end

#featured?Boolean

Returns:

  • (Boolean)


399
400
401
# File 'app/models/spree/taxon.rb', line 399

def featured?
  featured_sections.any?
end


403
404
405
# File 'app/models/spree/taxon.rb', line 403

def featured_sections
  @featured_sections ||= Spree::PageSections::FeaturedTaxon.published.by_taxon_id(id)
end

#generate_pretty_nameObject



335
336
337
# File 'app/models/spree/taxon.rb', line 335

def generate_pretty_name
  [parent&.pretty_name, name].compact.join(' -> ')
end

#generate_slugObject



339
340
341
342
343
344
345
346
347
# File 'app/models/spree/taxon.rb', line 339

def generate_slug
  if parent.present?
    [parent.permalink, (permalink.blank? ? name.to_url : permalink.split('/').last.to_url)].join('/')
  elsif permalink.blank?
    name.to_url
  else
    permalink.to_url
  end
end

#manual?Boolean

Returns:

  • (Boolean)


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

def manual?
  !automatic?
end

#manual_sort_order?Boolean

Returns:

  • (Boolean)


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

def manual_sort_order?
  sort_order == 'manual'
end

#page_builder_imageObject



160
161
162
# File 'app/models/spree/taxon.rb', line 160

def page_builder_image
  square_image.presence || image
end

#page_builder_urlObject



393
394
395
396
397
# File 'app/models/spree/taxon.rb', line 393

def page_builder_url
  return unless Spree::Core::Engine.routes.url_helpers.respond_to?(:nested_taxons_path)

  Spree::Core::Engine.routes.url_helpers.nested_taxons_path(self)
end

#products_matching_rules(opts = {}) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'app/models/spree/taxon.rb', line 175

def products_matching_rules(opts = {})
  return Spree::Product.none if manual? || rules.empty?

  storefront = opts[:storefront] || false
  currency = opts[:currency] || store.default_currency

  all_products = store.products.not_archived

  products_matcher_cache_key = [
    'products_matching_rules',
    cache_key_with_version,
    storefront,
    currency,
    all_products.cache_key_with_version
  ]

  all_products = all_products.active(currency: currency) if storefront

  any_rules_match_policy = rules_match_policy == 'any'
  products = any_rules_match_policy ? Spree::Product.none : all_products

  rules.each do |rule|
    if any_rules_match_policy
      product_ids = rule.apply(all_products).ids
      # it's safer to use this approach with ids as it will not break if the rule is not a simple where clause
      # and we will avoid `ArgumentError (Relation passed to #or must be structurally compatible. Incompatible values: [:group, :order, :joins, :readonly])` error
      products = products.or(all_products.where(id: product_ids)) if product_ids.any?
    else
      products = rule.apply(products)
    end
  end

  products
end


361
362
363
364
365
366
367
# File 'app/models/spree/taxon.rb', line 361

def regenerate_pretty_name_and_permalink
  Mobility.with_locale(nil) do
    update_columns(pretty_name: generate_pretty_name, permalink: generate_slug, updated_at: Time.current)
  end

  children.reload.each(&:regenerate_pretty_name_and_permalink_as_child)
end


369
370
371
372
373
374
375
# File 'app/models/spree/taxon.rb', line 369

def regenerate_pretty_name_and_permalink_as_child
  Mobility.with_locale(nil) do
    update_columns(pretty_name: generate_pretty_name, permalink: generate_slug, updated_at: Time.current)
  end

  children.reload.each(&:regenerate_pretty_name_and_permalink_as_child)
end

#regenerate_taxon_products(only_once: false) ⇒ Object

we need to create a new taxon product (classification) record for each product that matches the rules so we can later use them for product filtering and so on if we want to fire the service once during object lifecycle - pass only_once: true



213
214
215
216
217
218
# File 'app/models/spree/taxon.rb', line 213

def regenerate_taxon_products(only_once: false)
  if marked_for_regenerate_taxon_products?
    Spree::Taxons::RegenerateProducts.call(taxon: self)
    self.marked_for_regenerate_taxon_products = false if !frozen? && only_once
  end
end

#seo_titleObject

Return meta_title if set otherwise generates from taxon name



327
328
329
# File 'app/models/spree/taxon.rb', line 327

def seo_title
  meta_title.blank? ? name : meta_title
end


349
350
351
352
353
354
355
# File 'app/models/spree/taxon.rb', line 349

def set_permalink
  if Spree.use_translations?
    translations.each(&:set_permalink)
  else
    self.permalink = generate_slug
  end
end

#set_pretty_nameObject



331
332
333
# File 'app/models/spree/taxon.rb', line 331

def set_pretty_name
  self.pretty_name = generate_pretty_name
end

#slugObject



220
221
222
# File 'app/models/spree/taxon.rb', line 220

def slug
  permalink
end

#slug=(value) ⇒ Object



224
225
226
# File 'app/models/spree/taxon.rb', line 224

def slug=(value)
  self.permalink = value
end