Class: Spree::ProductGroup

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/spree/product_group.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_url(url) ⇒ Object

Testing utility: creates new ProductGroup from search permalink url. Follows conventions for accessing PGs from URLs, as decoded in routes



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'app/models/spree/product_group.rb', line 45

def self.from_url(url)
  pg = nil;
  case url
  when /\/t\/(.+?)\/s\/(.+)/  then taxons = $1; attrs = $2;
  when /\/t\/(.+?)\/pg\/(.+)/ then taxons = $1; pg_name = $2;
  when /(.*?)\/s\/(.+)/       then attrs = $2;
  when /(.*?)\/pg\/(.+)/      then pg_name = $2;
  else                        return(nil)
  end

  if pg_name && opg = ProductGroup.find_by_permalink(pg_name)
    pg = new.from_product_group(opg)
  elsif attrs
    attrs = url.split('/')
    pg = new.from_route(attrs)
  end
  taxon = taxons && taxons.split('/').last
  pg.add_scope('in_taxon', taxon) if taxon

  pg
end

.new_from_products(products, attrs = {}) ⇒ Object

Build a new product group with a scope to filter by specified products



194
195
196
197
198
# File 'app/models/spree/product_group.rb', line 194

def self.new_from_products(products, attrs = {})
  pg = new(attrs)
  pg.product_scopes.build(:name => 'with_ids', :arguments => [products.map(&:id).join(',')])
  pg
end

Instance Method Details

#add_scope(scope_name, arguments = []) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
# File 'app/models/spree/product_group.rb', line 94

def add_scope(scope_name, arguments=[])
  if scope_name.to_s !~ /eval|send|system|[^a-z0-9_!?]/
    self.product_scopes << ProductScope.new({
        :name => scope_name.to_s,
        :arguments => [*arguments]
      })
  else
    raise ArgumentError.new("'#{scope_name}` can't be used as scope")
  end
  self
end

#apply_on(scopish, use_order = true) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'app/models/spree/product_group.rb', line 106

def apply_on(scopish, use_order = true)
  # There's bug in AR, it doesn't merge :order, instead it takes order
  # from first nested_scope so we have to apply ordering FIRST.
  # see #2253 on rails LH
  base_product_scope = scopish
  if use_order && !self.order_scope.blank? && Product.respond_to?(self.order_scope.intern)
    base_product_scope = base_product_scope.send(self.order_scope)
  end

  return self.product_scopes.reject { |s| s.is_ordering? }.inject(base_product_scope) do |result, scope|
    scope.apply_on(result)
  end

end

#dynamic_products(use_order = true) ⇒ Object

returns chain of named scopes generated from order scope and product scopes.



122
123
124
# File 'app/models/spree/product_group.rb', line 122

def dynamic_products(use_order = true)
  apply_on(Product.group_by_products_id, use_order)
end

#from_product_group(opg) ⇒ Object



67
68
69
70
71
72
73
74
75
# File 'app/models/spree/product_group.rb', line 67

def from_product_group(opg)
  self.product_scopes = opg.product_scopes.map{|ps|
    ps = ps.clone;
    ps.product_group_id = nil;
    ps.product_group = self;
    ps
  }
  self
end

#from_route(attrs) ⇒ Object



77
78
79
80
81
82
83
84
# File 'app/models/spree/product_group.rb', line 77

def from_route(attrs)
  self.order_scope = attrs.pop if attrs.length % 2 == 1
  attrs.each_slice(2) do |scope|
    next unless Product.respond_to?(scope.first)
    add_scope(scope.first, scope.last.split(','))
  end
  self
end

#from_search(search_hash) ⇒ Object



86
87
88
89
90
91
92
# File 'app/models/spree/product_group.rb', line 86

def from_search(search_hash)
  search_hash.each_pair do |scope_name, scope_attribute|
    add_scope(scope_name, scope_attribute)
  end

  self
end

#generate_preview(size = ) ⇒ Object



168
169
170
171
172
# File 'app/models/spree/product_group.rb', line 168

def generate_preview(size = Spree::Config[:admin_pgroup_preview_size])
  count = self.class.count_by_sql ["SELECT COUNT(*) FROM spree_product_groups_products WHERE spree_product_groups_products.product_group_id = ?", self]

  return count, products.limit(size)
end

#include?(product) ⇒ Boolean

Returns:

  • (Boolean)


143
144
145
146
# File 'app/models/spree/product_group.rb', line 143

def include?(product)
  res = apply_on(Product.where(:id => product.id), false)
  res.count > 0
end

#order_scopeObject



179
180
181
182
183
# File 'app/models/spree/product_group.rb', line 179

def order_scope
  if scope = product_scopes.detect {|s| s.is_ordering?}
    scope.name
  end
end

#order_scope=(scope_name) ⇒ Object



185
186
187
188
189
190
191
# File 'app/models/spree/product_group.rb', line 185

def order_scope=(scope_name)
  if scope = product_scopes.detect {|s| s.is_ordering?}
    scope.update_attribute(:name, scope_name)
  else
    self.product_scopes.build(:name => scope_name, :arguments => [])
  end
end

#products(use_order = true) ⇒ Object

Does the final ordering if requested TODO: move the order stuff out of the above - is superfluous now



128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'app/models/spree/product_group.rb', line 128

def products(use_order = true)
  cached_group = Product.in_cached_group(self)
  if cached_group.limit(1).blank?
    dynamic_products(use_order)
  elsif !use_order
    cached_group
  else
    product_scopes.select { |s|
      s.is_ordering?
    }.inject(cached_group) { |res,order|
      order.apply_on(res)
    }
  end
end

#scopes_to_hashObject



148
149
150
151
152
153
154
# File 'app/models/spree/product_group.rb', line 148

def scopes_to_hash
  result = {}
  self.product_scopes.each do |scope|
    result[scope.name] = scope.arguments
  end
  result
end

#to_paramObject



156
157
158
# File 'app/models/spree/product_group.rb', line 156

def to_param
  permalink.present? ? permalink : (permalink_was || name.to_s.to_url)
end

#to_sObject



174
175
176
# File 'app/models/spree/product_group.rb', line 174

def to_s
  "<Spree::ProductGroup" + (id && "[#{id}]").to_s + ":'#{to_url}'>"
end

#update_membershipsObject



160
161
162
163
164
165
166
# File 'app/models/spree/product_group.rb', line 160

def update_memberships
  # wipe everything directly to avoid expensive in-rails sorting
  ActiveRecord::Base.connection.execute "DELETE FROM spree_product_groups_products WHERE product_group_id = #{self.id}"

  # and generate the new group entirely in SQL
  ActiveRecord::Base.connection.execute "INSERT INTO spree_product_groups_products #{dynamic_products(false).scoped(:select => "spree_products.id, #{self.id}").to_sql}"
end