Skip to content

Commit

Permalink
Add ransacker for product variants option values
Browse files Browse the repository at this point in the history
Introduce a ransacker `variants_option_values` on Spree::Product.
This ransacker enables dynamic filtering combined with ransack on
product variants option values.
For now, this attribute is geared towards usage in the admin interface.

https://activerecord-hackery.github.io/ransack/going-further/ransackers/
  • Loading branch information
rainerdema committed Sep 28, 2023
1 parent 556d11c commit a020947
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
18 changes: 17 additions & 1 deletion core/app/models/spree/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,24 @@ def find_or_build_master

alias :options :product_option_types

# The :variants_option_values ransacker filters Spree::Product based on
# variant option values ids.
#
# Usage:
# Spree::Product.ransack(
# variants_option_values_in: [option_value_id1, option_value_id2]
# ).result
ransacker :variants_option_values, formatter: proc { |v|
joins(variants_including_master: :option_values)
.where(spree_option_values: { id: v })
.distinct
.select(:id).arel if OptionValue.exists?(v)
} do |parent|
parent.table[:id]
end

self.allowed_ransackable_associations = %w[stores variants_including_master master variants]
self.allowed_ransackable_attributes = %w[name slug]
self.allowed_ransackable_attributes = %w[name slug variants_option_values]
self.allowed_ransackable_scopes = %i[available with_discarded with_all_variant_sku_cont with_kept_variant_sku_cont]

# @return [Boolean] true if there are any variants
Expand Down
52 changes: 52 additions & 0 deletions core/spec/models/spree/product_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,58 @@ class Extension < Spree::Base
end
end

context "ransacker :variants_option_values" do
it "filters products based on option values of their variants" do
product_1 = create(:product)
option_value_1 = create(:option_value)
create(:variant, product: product_1, option_values: [option_value_1])

result = Spree::Product.ransack(variants_option_values_in: [option_value_1.id]).result
expect(result).to contain_exactly(product_1)
end

it "returns multiple products for the same option value" do
product_1 = create(:product)
product_2 = create(:product)
option_value_1 = create(:option_value)
create(:variant, product: product_1, option_values: [option_value_1])
create(:variant, product: product_2, option_values: [option_value_1])

result = Spree::Product.ransack(variants_option_values_in: [option_value_1.id]).result
expect(result).to contain_exactly(product_1, product_2)
end

it "returns no products if there is no match" do
non_existing_option_value_id = 99999
result = Spree::Product.ransack(variants_option_values_in: [non_existing_option_value_id]).result
expect(result).to be_empty
end

it "returns products that match any of the provided option value IDs" do
product_1 = create(:product)
product_2 = create(:product)
option_value_1 = create(:option_value)
option_value_2 = create(:option_value)
create(:variant, product: product_1, option_values: [option_value_1])
create(:variant, product: product_2, option_values: [option_value_2])

result = Spree::Product.ransack(variants_option_values_in: [option_value_1.id, option_value_2.id]).result
expect(result).to contain_exactly(product_1, product_2)
end

it "doesn't return products that have other option values not in the query" do
product_1 = create(:product)
product_2 = create(:product)
option_value_1 = create(:option_value)
option_value_2 = create(:option_value)
create(:variant, product: product_1, option_values: [option_value_1])
create(:variant, product: product_2, option_values: [option_value_2])

result = Spree::Product.ransack(variants_option_values_in: [option_value_1.id]).result
expect(result).not_to include(product_2)
end
end

describe "ransack scopes" do
context "available scope" do
subject { described_class.ransack(available: true).result }
Expand Down

0 comments on commit a020947

Please sign in to comment.