diff --git a/core/app/models/spree/product.rb b/core/app/models/spree/product.rb index 1754e939497..03193148ec0 100644 --- a/core/app/models/spree/product.rb +++ b/core/app/models/spree/product.rb @@ -291,6 +291,10 @@ def gallery @gallery ||= Spree::Config.product_gallery_class.new(self) end + def brand + Spree::Config.brand_selector_class.new(self).call + end + private def any_variants_not_track_inventory? diff --git a/core/app/models/spree/taxon_brand_selector.rb b/core/app/models/spree/taxon_brand_selector.rb new file mode 100644 index 00000000000..4a0a0dce0bd --- /dev/null +++ b/core/app/models/spree/taxon_brand_selector.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Spree + class TaxonBrandSelector + BRANDS_TAXONOMY_NAME = "Brands" + + def initialize(product) + @product = product + end + + def call + product.taxons + .joins(:taxonomy) + .where(spree_taxonomies: { name: BRANDS_TAXONOMY_NAME }) + .first + end + + private + + attr_reader :product + end +end diff --git a/core/config/locales/en.yml b/core/config/locales/en.yml index 02a8ca8aa07..e7e1d1910a5 100644 --- a/core/config/locales/en.yml +++ b/core/config/locales/en.yml @@ -1075,6 +1075,8 @@ en: billing: Billing billing_address: Billing Address both: Both + brand: Brand + brands: Brands calculated_reimbursements: Calculated Reimbursements calculator: Calculator calculator_settings_warning: If you are changing the calculator type or preference source, you must save first before you can edit the calculator settings diff --git a/core/lib/spree/app_configuration.rb b/core/lib/spree/app_configuration.rb index 8b0223eeb59..631a609d18d 100644 --- a/core/lib/spree/app_configuration.rb +++ b/core/lib/spree/app_configuration.rb @@ -522,6 +522,13 @@ def payment_canceller # Spree::StoreCreditPrioritizer. class_name_attribute :store_credit_prioritizer_class, default: 'Spree::StoreCreditPrioritizer' + # Allows finding brand for product. + # + # @!attribute [rw] brand_selector_class + # @return [Class] a class with the same public interfaces as + # Spree::TaxonBrandSelector. + class_name_attribute :brand_selector_class, default: 'Spree::TaxonBrandSelector' + # @!attribute [rw] taxon_image_style_default # # Defines which style to default to when style is not provided diff --git a/core/spec/models/spree/taxon_brand_selector_spec.rb b/core/spec/models/spree/taxon_brand_selector_spec.rb new file mode 100644 index 00000000000..7d2d4721e60 --- /dev/null +++ b/core/spec/models/spree/taxon_brand_selector_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Spree::TaxonBrandSelector, type: :model do + let(:taxonomy) { create(:taxonomy, name: "Brands") } + let(:taxon) { create(:taxon, taxonomy: taxonomy, name: "Brand A") } + let(:product) { create(:product, taxons: [taxon]) } + + subject { described_class.new(product) } + + describe "#call" do + context "when the product has a taxon under the 'Brands' taxonomy" do + it "returns the first taxon under 'Brands'" do + expect(subject.call).to eq(taxon) + end + end + + context "when the product has multiple taxons under the 'Brands' taxonomy" do + let(:taxon_b) { create(:taxon, taxonomy: taxonomy, name: "Brand B") } + before { product.taxons << taxon_b } + + it "returns the first taxon under 'Brands'" do + expect(subject.call).to eq(taxon) + end + end + + context "when the product does not have a taxon under the 'Brands' taxonomy" do + let(:other_taxonomy) { create(:taxonomy, name: "Categories") } + let(:other_taxon) { create(:taxon, taxonomy: other_taxonomy, name: "Category A") } + let(:product) { create(:product, taxons: [other_taxon]) } + + it "returns nil" do + expect(subject.call).to be_nil + end + end + + context "when the product has no taxons" do + let(:product) { create(:product) } + + it "returns nil" do + expect(subject.call).to be_nil + end + end + end +end diff --git a/sample/db/samples/taxons.rb b/sample/db/samples/taxons.rb index 8d96e53e3a8..f882792a61e 100644 --- a/sample/db/samples/taxons.rb +++ b/sample/db/samples/taxons.rb @@ -4,6 +4,7 @@ Spree::Sample.load_sample("products") categories = Spree::Taxonomy.find_by!(name: "Categories") +brands = Spree::Taxonomy.find_by!(name: "Brands") products = { solidus_bottles: "Solidus Water Bottle", @@ -29,6 +30,29 @@ name: "Categories", taxonomy: categories, }, + { + name: "Brands", + taxonomy: brands + }, + { + name: "Solidus", + taxonomy: brands, + parent: "Brands", + products: [ + products[:solidus_tote], + products[:solidus_hoodie], + products[:solidus_mug_set], + products[:solidus_hat], + products[:solidus_sticker], + products[:solidus_notebook], + products[:solidus_tshirt], + products[:solidus_long_sleeve_tee], + products[:solidus_dark_tee], + products[:solidus_bottles], + products[:solidus_canvas_tote], + products[:solidus_cap] + ] + }, { name: "Clothing", taxonomy: categories,