Commit c84e0cabbd250d491fba169e79b9c2e7baba3210
1 parent
b0e5e0c9
Exists in
master
and in
28 other branches
product-category: fetch only necessary categories
Instead of fetching every category to display the icons, fetch only 3 of them through the correct sql query. This also fixes a big memory leak. (ActionItem3084)
Showing
7 changed files
with
55 additions
and
39 deletions
Show diff stats
app/helpers/application_helper.rb
... | ... | @@ -514,24 +514,25 @@ module ApplicationHelper |
514 | 514 | |
515 | 515 | def profile_cat_icons( profile ) |
516 | 516 | if profile.class == Enterprise |
517 | - icons = profile.product_categories.map{ |c| c.size > 1 ? c[1] : nil }. | |
518 | - compact.uniq.map do |c| | |
519 | - cat_name = c.gsub( /[-_\s,.;'"]+/, '_' ) | |
520 | - cat_icon = "/images/icons-cat/#{cat_name}.png" | |
521 | - if ! File.exists? RAILS_ROOT.to_s() + '/public/' + cat_icon | |
522 | - cat_icon = '/images/icons-cat/undefined.png' | |
523 | - end | |
524 | - content_tag('span', | |
525 | - content_tag( 'span', c ), | |
526 | - :title => c, | |
527 | - :class => 'product-cat-icon cat_icon_' + cat_name, | |
528 | - :style => "background-image:url(#{cat_icon})" | |
529 | - ) | |
530 | - end.join("\n").html_safe | |
531 | - content_tag('div', | |
532 | - content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons, | |
533 | - :class => 'product-category-icons' | |
517 | + icons = profile.product_categories.unique_by_level(2).limit(3).map do |c| | |
518 | + filtered_category = c.filtered_category.blank? ? c.path.split('/').last : c.filtered_category | |
519 | + category_title = filtered_category.split(/[-_\s,.;'"]+/).map(&:capitalize).join(' ') | |
520 | + category_name = category_title.gsub(' ', '_' ) | |
521 | + category_icon = "/images/icons-cat/#{category_name}.png" | |
522 | + if ! File.exists? RAILS_ROOT.to_s() + '/public/' + category_icon | |
523 | + category_icon = '/images/icons-cat/undefined.png' | |
524 | + end | |
525 | + content_tag('span', | |
526 | + content_tag( 'span', category_title ), | |
527 | + :title => category_title, | |
528 | + :class => 'product-cat-icon cat_icon_' + category_name, | |
529 | + :style => "background-image:url(#{category_icon})" | |
534 | 530 | ) |
531 | + end.join("\n").html_safe | |
532 | + content_tag('div', | |
533 | + content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons, | |
534 | + :class => 'product-category-icons' | |
535 | + ) | |
535 | 536 | else |
536 | 537 | '' |
537 | 538 | end | ... | ... |
app/models/enterprise.rb
... | ... | @@ -17,7 +17,7 @@ class Enterprise < Organization |
17 | 17 | has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people' |
18 | 18 | |
19 | 19 | def product_categories |
20 | - products.includes(:product_category).map{|p| p.category_full_name}.compact | |
20 | + ProductCategory.by_enterprise(self) | |
21 | 21 | end |
22 | 22 | |
23 | 23 | N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') | ... | ... |
app/models/product.rb
... | ... | @@ -88,10 +88,6 @@ class Product < ActiveRecord::Base |
88 | 88 | image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size |
89 | 89 | end |
90 | 90 | |
91 | - def category_full_name | |
92 | - product_category ? product_category.full_name.split('/') : nil | |
93 | - end | |
94 | - | |
95 | 91 | acts_as_having_image |
96 | 92 | |
97 | 93 | def save_image | ... | ... |
app/models/product_category.rb
... | ... | @@ -3,6 +3,15 @@ class ProductCategory < Category |
3 | 3 | has_many :products |
4 | 4 | has_many :inputs |
5 | 5 | |
6 | + named_scope :unique, :select => 'DISTINCT ON (path) categories.*' | |
7 | + named_scope :by_enterprise, lambda { |enterprise| { | |
8 | + :joins => :products, | |
9 | + :conditions => ['products.profile_id = ?', enterprise.id] | |
10 | + }} | |
11 | + named_scope :unique_by_level, lambda { |level| { | |
12 | + :select => "DISTINCT ON (filtered_category) split_part(path, '/', #{level}) AS filtered_category, categories.*" | |
13 | + }} | |
14 | + | |
6 | 15 | def all_products |
7 | 16 | Product.find(:all, :conditions => { :product_category_id => (all_children << self).map(&:id) }) |
8 | 17 | end | ... | ... |
test/unit/enterprise_test.rb
... | ... | @@ -234,12 +234,12 @@ class EnterpriseTest < ActiveSupport::TestCase |
234 | 234 | assert enterprise.enable(person) |
235 | 235 | end |
236 | 236 | |
237 | - should 'list product categories full name' do | |
237 | + should 'list product categories' do | |
238 | 238 | subcategory = fast_create(ProductCategory, :name => 'Products subcategory', :parent_id => @product_category.id) |
239 | 239 | ent = fast_create(Enterprise, :name => 'test ent', :identifier => 'test_ent') |
240 | 240 | p = ent.products.create!(:name => 'test prod', :product_category => subcategory) |
241 | 241 | |
242 | - assert_equal [p.category_full_name], ent.product_categories | |
242 | + assert_equivalent [subcategory], ent.product_categories | |
243 | 243 | end |
244 | 244 | |
245 | 245 | should 'not create a products block for enterprise if environment do not let' do | ... | ... |
test/unit/product_category_test.rb
... | ... | @@ -36,4 +36,29 @@ class ProductCategoryTest < ActiveSupport::TestCase |
36 | 36 | assert_equal [c11], ProductCategory.menu_categories(c1, nil) |
37 | 37 | end |
38 | 38 | |
39 | + should 'provide a scope based on the enterprise' do | |
40 | + enterprise = fast_create(Enterprise) | |
41 | + c1 = ProductCategory.create!(:name => 'test cat 1', :environment => Environment.default) | |
42 | + c2 = ProductCategory.create!(:name => 'test cat 2', :environment => Environment.default) | |
43 | + c3 = ProductCategory.create!(:name => 'test cat 3', :environment => Environment.default) | |
44 | + p1 = Product.create(:name => 'product1', :product_category => c1, :profile_id => enterprise.id) | |
45 | + p2 = Product.create(:name => 'product2', :product_category => c1, :profile_id => enterprise.id) | |
46 | + p3 = Product.create(:name => 'product3', :product_category => c2, :profile_id => enterprise.id) | |
47 | + | |
48 | + scope = ProductCategory.by_enterprise(enterprise) | |
49 | + | |
50 | + assert_equal ActiveRecord::NamedScope::Scope, scope.class | |
51 | + assert_equivalent [c1,c2], scope | |
52 | + end | |
53 | + | |
54 | + should 'fetch unique categories by level' do | |
55 | + c1 = ProductCategory.create!(:name => 'test cat 1', :environment => Environment.default) | |
56 | + c11 = ProductCategory.create!(:name => 'test cat 11', :environment => Environment.default, :parent => c1) | |
57 | + c12 = ProductCategory.create!(:name => 'test cat 12', :environment => Environment.default, :parent => c1) | |
58 | + c111 = ProductCategory.create!(:name => 'test cat 111', :environment => Environment.default, :parent => c11) | |
59 | + c112 = ProductCategory.create!(:name => 'test cat 112', :environment => Environment.default, :parent => c11) | |
60 | + | |
61 | + assert_equivalent ['', 'test-cat-11', 'test-cat-12'], ProductCategory.unique_by_level(2).map(&:filtered_category) | |
62 | + end | |
63 | + | |
39 | 64 | end | ... | ... |
test/unit/product_test.rb
... | ... | @@ -89,21 +89,6 @@ class ProductTest < ActiveSupport::TestCase |
89 | 89 | end |
90 | 90 | end |
91 | 91 | |
92 | - should 'calculate category full name' do | |
93 | - cat = mock | |
94 | - cat.expects(:full_name).returns('A/B/C') | |
95 | - | |
96 | - p = Product.new | |
97 | - p.stubs(:product_category).returns(cat) | |
98 | - assert_equal ['A','B','C'], p.category_full_name | |
99 | - end | |
100 | - | |
101 | - should 'return a nil cateory full name when not categorized' do | |
102 | - p = Product.new | |
103 | - p.stubs(:product_category).returns(nil) | |
104 | - assert_equal nil, p.category_full_name | |
105 | - end | |
106 | - | |
107 | 92 | should 'have same lat and lng of its enterprise' do |
108 | 93 | ent = fast_create(Enterprise, :name => 'test enterprise', :identifier => 'test_enterprise', :lat => 30.0, :lng => 30.0) |
109 | 94 | prod = ent.products.create!(:name => 'test product', :product_category => @product_category) | ... | ... |