forked from spree-contrib/spree_related_products
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adapt for variant to variant relations
- Loading branch information
Showing
5 changed files
with
193 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# frozen_string_literal: true | ||
|
||
module Spree | ||
module VariantDecorator | ||
def self.prepended(base) | ||
base.has_many :relations, -> { order(:position) }, class_name: 'Spree::Relation', as: :relatable | ||
base.has_many :relation_types, -> { unscope(:order).distinct }, class_name: 'Spree::RelationType', through: :relations | ||
|
||
# When a Spree::Product is destroyed, we also want to destroy all | ||
# Spree::Relations "from" it as well as "to" it. | ||
base.after_destroy :destroy_product_relations | ||
base.extend ClassMethods | ||
end | ||
|
||
module ClassMethods | ||
# Returns all the Spree::RelationType's which apply_to this class. | ||
def relation_types | ||
Spree::RelationType.where(applies_to: to_s).order(:name) | ||
end | ||
|
||
def relation_filter | ||
joins(:product).where('spree_products.deleted_at' => nil) | ||
.where('spree_products.available_on IS NOT NULL') | ||
.where('spree_products.status' => :active) | ||
.references(self) | ||
end | ||
end | ||
|
||
# Decides if there is a relevant Spree::RelationType related to this class | ||
# which should be returned for this method. | ||
# | ||
# If so, it calls relations_for_relation_type. Otherwise it passes | ||
# it up the inheritance chain. | ||
# def method_missing(method, *args) | ||
# relation_type = find_relation_type(method) | ||
# if relation_type.nil? | ||
# super | ||
# else | ||
# relations_for_relation_type(relation_type) | ||
# end | ||
# end | ||
|
||
def has_related_products?(relation_method) | ||
find_relation_type(relation_method).present? | ||
end | ||
|
||
def destroy_product_relations | ||
# First we destroy relationships "from" this Product to others. | ||
relations.destroy_all | ||
# Next we destroy relationships "to" this Product. | ||
Spree::Relation.where(related_to_type: self.class.to_s).where(related_to_id: id).destroy_all | ||
end | ||
|
||
private | ||
|
||
def find_relation_type(relation_name) | ||
self.class.relation_types.detect do |rt| | ||
format_name(rt.name) == format_name(relation_name) | ||
end | ||
rescue ActiveRecord::StatementInvalid | ||
# This exception is throw if the relation_types table does not exist. | ||
# And this method is getting invoked during the execution of a migration | ||
# from another extension when both are used in a project. | ||
nil | ||
end | ||
|
||
# Returns all the Products that are related to this record for the given RelationType. | ||
# | ||
# Uses the Relations to find all the related items, and then filters | ||
# them using +Product.relation_filter+ to remove unwanted items. | ||
def relations_for_relation_type(relation_type) | ||
# Find all the relations that belong to us for this RelationType, ordered by position | ||
related_ids = relations.where(relation_type_id: relation_type.id) | ||
.order(:position) | ||
.select(:related_to_id) | ||
|
||
# Construct a query for all these records | ||
result = self.class.where(id: related_ids) | ||
|
||
# Merge in the relation_filter if it's available | ||
result = result.merge(self.class.relation_filter) if relation_filter | ||
|
||
# make sure results are in same order as related_ids array (position order) | ||
result.where(id: related_ids).order(:position) if result.present? | ||
|
||
result | ||
end | ||
|
||
# Simple accessor for the class-level relation_filter. | ||
# Could feasibly be overloaded to filter results relative to this | ||
# record (eg. only higher priced items) | ||
def relation_filter | ||
self.class.relation_filter | ||
end | ||
|
||
def format_name(name) | ||
name.to_s.downcase.tr(' ', '_').pluralize | ||
end | ||
end | ||
end | ||
|
||
::Spree::Variant.prepend(Spree::VariantDecorator) |
66 changes: 66 additions & 0 deletions
66
app/views/spree/admin/products/_related_variants_table.html.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<% variants.each do |variant| %> | ||
<% if variant.relations.any? %> | ||
<table class="table sortable" data-hook="products_table" data-sortable-link="<%= update_positions_admin_product_relations_url(variant.product) %>"> | ||
<caption><%= "Relations for Variant SKU: #{variant.sku} Option: #{variant.options_text}" %></caption> | ||
<colgroup> | ||
<col style="width: 3%" /> | ||
<col style="width: 7%" /> | ||
<col style="width: 8%" /> | ||
<col style="width: 35%" /> | ||
<col style="width: 15%" /> | ||
<col style="width: 10%" /> | ||
<col style="width: 20%" /> | ||
<col style="width: 2%" /> | ||
</colgroup> | ||
<thead> | ||
<tr data-hook="products_header"> | ||
<th></th> | ||
<th>SKU</th> | ||
<th>Related To Type</th> | ||
<th><%= Spree.t(:name) %></th> | ||
<th><%= Spree.t(:option) %></th> | ||
<th><%= Spree.t(:type) %></th> | ||
<th><%= Spree.t(:quantity) %>%></th> | ||
<th class="actions"></th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% variant.relations.each do |relation| %> | ||
<tr id="<%= spree_dom_id relation %>" data-hook="products_row"> | ||
<td class="handle move-handle"> | ||
<% if Spree.version.to_d >= 4.2 && defined?(svg_icon) %> | ||
<%= svg_icon name: "sort.svg", width: '18', height: '18' %> | ||
<% else %> | ||
<span class="icon icon-move handle"></span> | ||
<% end %> | ||
</td> | ||
<td><%= relation.related_to.sku %></td> | ||
<td><%= relation.related_to_type %></td> | ||
<td><%= relation.related_to.name %></td> | ||
<td><%= relation.related_to.try(:options_text) %></td> | ||
<%# if defined? Spree::Frontend %> | ||
<%# binding.break %> | ||
<!-- <td><%#= link_to relation.related_to.name, relation.related_to %></td> --> | ||
<%# else %> | ||
<!-- <td><%#= link_to relation.related_to.name, admin_product_path(relation.related_to) %></td> --> | ||
<%# end %> | ||
<td><%= relation.relation_type.name %></td> | ||
<td> | ||
<%= form_for relation, url: admin_variant_relation_path(relation.relatable, relation) do |f| %> | ||
<div class="input-group justify-content-center"> | ||
<%= f.text_field :quantity, class: 'form-control text-center my-1 w-20' %> | ||
<span class="input-group-btn"> | ||
<%= f.button Spree.t(:update), type: 'submit', class: 'btn btn-primary m-1' %> | ||
</span> | ||
</div> | ||
<% end %> | ||
</td> | ||
<td class="actions"> | ||
<%= link_to_delete relation, url: admin_variant_relation_url(relation.relatable, relation), no_text: true %> | ||
</td> | ||
</tr> | ||
<% end %> | ||
</tbody> | ||
</table> | ||
<% end %> | ||
<% end %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters