mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Merge pull request #5868 from luisramos0/taxonomies
[Bye bye Spree] Bring models taxon and taxonomy from spree_core
This commit is contained in:
21
app/models/spree/classification.rb
Normal file
21
app/models/spree/classification.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
class Classification < ActiveRecord::Base
|
||||
self.table_name = 'spree_products_taxons'
|
||||
belongs_to :product, class_name: "Spree::Product", touch: true
|
||||
belongs_to :taxon, class_name: "Spree::Taxon", touch: true
|
||||
|
||||
before_destroy :dont_destroy_if_primary_taxon
|
||||
|
||||
private
|
||||
|
||||
def dont_destroy_if_primary_taxon
|
||||
return unless product.primary_taxon == taxon
|
||||
|
||||
errors.add :base, I18n.t(:spree_classification_primary_taxon_error, taxon: taxon.name,
|
||||
product: product.name)
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,15 +0,0 @@
|
||||
Spree::Classification.class_eval do
|
||||
belongs_to :product, class_name: "Spree::Product", touch: true
|
||||
belongs_to :taxon, class_name: "Spree::Taxon", touch: true
|
||||
|
||||
before_destroy :dont_destroy_if_primary_taxon
|
||||
|
||||
private
|
||||
|
||||
def dont_destroy_if_primary_taxon
|
||||
if product.primary_taxon == taxon
|
||||
errors.add :base, I18n.t(:spree_classification_primary_taxon_error, taxon: taxon.name, product: product.name)
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
113
app/models/spree/taxon.rb
Normal file
113
app/models/spree/taxon.rb
Normal file
@@ -0,0 +1,113 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
class Taxon < ActiveRecord::Base
|
||||
acts_as_nested_set dependent: :destroy
|
||||
|
||||
belongs_to :taxonomy, class_name: 'Spree::Taxonomy', touch: true
|
||||
has_many :classifications, dependent: :destroy
|
||||
has_many :products, through: :classifications
|
||||
|
||||
before_create :set_permalink
|
||||
|
||||
validates :name, presence: true
|
||||
|
||||
has_attached_file :icon,
|
||||
styles: { mini: '32x32>', normal: '128x128>' },
|
||||
default_style: :mini,
|
||||
url: '/spree/taxons/:id/:style/:basename.:extension',
|
||||
path: ':rails_root/public/spree/taxons/:id/:style/:basename.:extension',
|
||||
default_url: '/assets/default_taxon.png'
|
||||
|
||||
include Spree::Core::S3Support
|
||||
supports_s3 :icon
|
||||
|
||||
# Indicate which filters should be used for this taxon
|
||||
def applicable_filters
|
||||
[]
|
||||
end
|
||||
|
||||
# Return meta_title if set otherwise generates from root name and/or taxon name
|
||||
def seo_title
|
||||
if meta_title
|
||||
meta_title
|
||||
else
|
||||
root? ? name : "#{root.name} - #{name}"
|
||||
end
|
||||
end
|
||||
|
||||
# Creates permalink based on Stringex's .to_url method
|
||||
def set_permalink
|
||||
if parent.present?
|
||||
self.permalink = [parent.permalink, permalink_end].join('/')
|
||||
elsif permalink.blank?
|
||||
self.permalink = name.to_url
|
||||
end
|
||||
end
|
||||
|
||||
# For #2759
|
||||
def to_param
|
||||
permalink
|
||||
end
|
||||
|
||||
def active_products
|
||||
scope = products.active
|
||||
scope
|
||||
end
|
||||
|
||||
def pretty_name
|
||||
ancestor_chain = ancestors.inject("") do |name, ancestor|
|
||||
name += "#{ancestor.name} -> "
|
||||
end
|
||||
ancestor_chain + name.to_s
|
||||
end
|
||||
|
||||
# Find all the taxons of supplied products for each enterprise, indexed by enterprise.
|
||||
# Format: {enterprise_id => [taxon_id, ...]}
|
||||
def self.supplied_taxons
|
||||
taxons = {}
|
||||
|
||||
Spree::Taxon.
|
||||
joins(products: :supplier).
|
||||
select('spree_taxons.*, enterprises.id AS enterprise_id').
|
||||
each do |t|
|
||||
taxons[t.enterprise_id.to_i] ||= Set.new
|
||||
taxons[t.enterprise_id.to_i] << t.id
|
||||
end
|
||||
|
||||
taxons
|
||||
end
|
||||
|
||||
# Find all the taxons of distributed products for each enterprise, indexed by enterprise.
|
||||
# May return :all taxons (distributed in open and closed order cycles),
|
||||
# or :current taxons (distributed in an open order cycle).
|
||||
#
|
||||
# Format: {enterprise_id => [taxon_id, ...]}
|
||||
def self.distributed_taxons(which_taxons = :all)
|
||||
ents_and_vars = ExchangeVariant.joins(exchange: :order_cycle).merge(Exchange.outgoing)
|
||||
.select("DISTINCT variant_id, receiver_id AS enterprise_id")
|
||||
|
||||
ents_and_vars = ents_and_vars.merge(OrderCycle.active) if which_taxons == :current
|
||||
|
||||
taxons = Spree::Taxon
|
||||
.select("DISTINCT spree_taxons.id, ents_and_vars.enterprise_id")
|
||||
.joins(products: :variants_including_master)
|
||||
.joins("
|
||||
INNER JOIN (#{ents_and_vars.to_sql}) AS ents_and_vars
|
||||
ON spree_variants.id = ents_and_vars.variant_id")
|
||||
|
||||
taxons.each_with_object({}) do |t, ts|
|
||||
ts[t.enterprise_id.to_i] ||= Set.new
|
||||
ts[t.enterprise_id.to_i] << t.id
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def permalink_end
|
||||
return name.to_url if permalink.blank?
|
||||
|
||||
permalink.split('/').last
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,47 +0,0 @@
|
||||
Spree::Taxon.class_eval do
|
||||
has_many :classifications, dependent: :destroy
|
||||
|
||||
# Indicate which filters should be used for this taxon
|
||||
def applicable_filters
|
||||
fs = []
|
||||
# fs << Spree::ProductFilters.distributor_filter if Spree::ProductFilters.respond_to? :distributor_filter
|
||||
fs
|
||||
end
|
||||
|
||||
# Find all the taxons of supplied products for each enterprise, indexed by enterprise.
|
||||
# Format: {enterprise_id => [taxon_id, ...]}
|
||||
def self.supplied_taxons
|
||||
taxons = {}
|
||||
|
||||
Spree::Taxon.
|
||||
joins(products: :supplier).
|
||||
select('spree_taxons.*, enterprises.id AS enterprise_id').
|
||||
each do |t|
|
||||
taxons[t.enterprise_id.to_i] ||= Set.new
|
||||
taxons[t.enterprise_id.to_i] << t.id
|
||||
end
|
||||
|
||||
taxons
|
||||
end
|
||||
|
||||
# Find all the taxons of distributed products for each enterprise, indexed by enterprise.
|
||||
# May return :all taxons (distributed in open and closed order cycles),
|
||||
# or :current taxons (distributed in an open order cycle).
|
||||
#
|
||||
# Format: {enterprise_id => [taxon_id, ...]}
|
||||
def self.distributed_taxons(which_taxons = :all)
|
||||
ents_and_vars = ExchangeVariant.joins(exchange: :order_cycle).merge(Exchange.outgoing)
|
||||
.select("DISTINCT variant_id, receiver_id AS enterprise_id")
|
||||
|
||||
ents_and_vars = ents_and_vars.merge(OrderCycle.active) if which_taxons == :current
|
||||
|
||||
taxons = Spree::Taxon
|
||||
.select("DISTINCT spree_taxons.id, ents_and_vars.enterprise_id").joins(products: :variants_including_master)
|
||||
.joins("INNER JOIN (#{ents_and_vars.to_sql}) AS ents_and_vars ON spree_variants.id = ents_and_vars.variant_id")
|
||||
|
||||
taxons.each_with_object({}) do |t, ts|
|
||||
ts[t.enterprise_id.to_i] ||= Set.new
|
||||
ts[t.enterprise_id.to_i] << t.id
|
||||
end
|
||||
end
|
||||
end
|
||||
24
app/models/spree/taxonomy.rb
Normal file
24
app/models/spree/taxonomy.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
class Taxonomy < ActiveRecord::Base
|
||||
validates :name, presence: true
|
||||
|
||||
has_many :taxons
|
||||
has_one :root, -> { where parent_id: nil }, class_name: "Spree::Taxon", dependent: :destroy
|
||||
|
||||
after_save :set_name
|
||||
|
||||
default_scope -> { order("#{table_name}.position") }
|
||||
|
||||
private
|
||||
|
||||
def set_name
|
||||
if root
|
||||
root.update_column(:name, name)
|
||||
else
|
||||
self.root = Taxon.create!(taxonomy_id: id, name: name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
module Spree
|
||||
describe Taxon do
|
||||
let(:taxon) { Spree::Taxon.new(name: "Ruby on Rails") }
|
||||
|
||||
let(:e) { create(:supplier_enterprise) }
|
||||
let!(:t1) { create(:taxon) }
|
||||
let!(:t2) { create(:taxon) }
|
||||
@@ -46,5 +50,51 @@ module Spree
|
||||
end.to change { taxon2.reload.updated_at }
|
||||
end
|
||||
end
|
||||
|
||||
context "set_permalink" do
|
||||
it "should set permalink correctly when no parent present" do
|
||||
taxon.set_permalink
|
||||
expect(taxon.permalink).to eq "ruby-on-rails"
|
||||
end
|
||||
|
||||
it "should support Chinese characters" do
|
||||
taxon.name = "你好"
|
||||
taxon.set_permalink
|
||||
expect(taxon.permalink).to eq 'ni-hao'
|
||||
end
|
||||
|
||||
context "with parent taxon" do
|
||||
before do
|
||||
allow(taxon).to receive_messages parent_id: 123
|
||||
allow(taxon).to receive_messages parent: build(:taxon, permalink: "brands")
|
||||
end
|
||||
|
||||
it "should set permalink correctly when taxon has parent" do
|
||||
taxon.set_permalink
|
||||
expect(taxon.permalink).to eq "brands/ruby-on-rails"
|
||||
end
|
||||
|
||||
it "should set permalink correctly with existing permalink present" do
|
||||
taxon.permalink = "b/rubyonrails"
|
||||
taxon.set_permalink
|
||||
expect(taxon.permalink).to eq "brands/rubyonrails"
|
||||
end
|
||||
|
||||
it "should support Chinese characters" do
|
||||
taxon.name = "我"
|
||||
taxon.set_permalink
|
||||
expect(taxon.permalink).to eq "brands/wo"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Regression test for Spree #2620
|
||||
context "creating a child node using first_or_create" do
|
||||
let(:taxonomy) { create(:taxonomy) }
|
||||
|
||||
it "does not error out" do
|
||||
expect { taxonomy.root.children.where(name: "Some name").first_or_create }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
19
spec/models/spree/taxonomy_spec.rb
Normal file
19
spec/models/spree/taxonomy_spec.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::Taxonomy do
|
||||
context "#destroy" do
|
||||
before do
|
||||
@taxonomy = create(:taxonomy)
|
||||
@root_taxon = @taxonomy.root
|
||||
@child_taxon = create(:taxon, taxonomy_id: @taxonomy.id, parent: @root_taxon)
|
||||
end
|
||||
|
||||
it "should destroy all associated taxons" do
|
||||
@taxonomy.destroy
|
||||
expect{ Spree::Taxon.find(@root_taxon.id) }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
expect{ Spree::Taxon.find(@child_taxon.id) }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user