/
product_decorator.rb
72 lines (60 loc) · 2.5 KB
/
product_decorator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Spree::Product.class_eval do
has_many :relations, :as => :relatable
# Returns all the Spree::RelationType's which apply_to this class.
def self.relation_types
Spree::RelationType.find_all_by_applies_to(self.to_s, :order => :name)
end
# The AREL Relations that will be used to filter the resultant items.
#
# By default this will remove any items which are deleted, or not yet available.
#
# You can override this method to fine tune the filter. For example,
# to only return Spree::Product's with more than 2 items in stock, you could
# do the following:
#
# def self.relation_filter
# set = super
# set.where('spree_products.count_on_hand >= 2')
# end
#
# This could also feasibly be overridden to sort the result in a
# particular order, or restrict the number of items returned.
def self.relation_filter
where('spree_products.deleted_at' => nil).where('spree_products.available_on IS NOT NULL').where('spree_products.available_on <= ?', Time.now)
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)
# Fix for Ruby 1.9
raise NoMethodError if method == :to_ary
relation_type = self.class.relation_types.detect { |rt| rt.name.downcase.gsub(" ", "_").pluralize == method.to_s.downcase }
if relation_type.nil?
super
else
relations_for_relation_type(relation_type)
end
end
private
# 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
related_ids = relations.where(:relation_type_id => relation_type.id).select(:related_to_id).collect(&: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.scoped) if relation_filter
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
end