Commit c84e0cabbd250d491fba169e79b9c2e7baba3210
1 parent
b0e5e0c9
Exists in
master
and in
29 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,24 +514,25 @@ module ApplicationHelper | ||
514 | 514 | ||
515 | def profile_cat_icons( profile ) | 515 | def profile_cat_icons( profile ) |
516 | if profile.class == Enterprise | 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 | else | 536 | else |
536 | '' | 537 | '' |
537 | end | 538 | end |
app/models/enterprise.rb
@@ -17,7 +17,7 @@ class Enterprise < Organization | @@ -17,7 +17,7 @@ class Enterprise < Organization | ||
17 | has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people' | 17 | has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people' |
18 | 18 | ||
19 | def product_categories | 19 | def product_categories |
20 | - products.includes(:product_category).map{|p| p.category_full_name}.compact | 20 | + ProductCategory.by_enterprise(self) |
21 | end | 21 | end |
22 | 22 | ||
23 | N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') | 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,10 +88,6 @@ class Product < ActiveRecord::Base | ||
88 | image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size | 88 | image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size |
89 | end | 89 | end |
90 | 90 | ||
91 | - def category_full_name | ||
92 | - product_category ? product_category.full_name.split('/') : nil | ||
93 | - end | ||
94 | - | ||
95 | acts_as_having_image | 91 | acts_as_having_image |
96 | 92 | ||
97 | def save_image | 93 | def save_image |
app/models/product_category.rb
@@ -3,6 +3,15 @@ class ProductCategory < Category | @@ -3,6 +3,15 @@ class ProductCategory < Category | ||
3 | has_many :products | 3 | has_many :products |
4 | has_many :inputs | 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 | def all_products | 15 | def all_products |
7 | Product.find(:all, :conditions => { :product_category_id => (all_children << self).map(&:id) }) | 16 | Product.find(:all, :conditions => { :product_category_id => (all_children << self).map(&:id) }) |
8 | end | 17 | end |
test/unit/enterprise_test.rb
@@ -234,12 +234,12 @@ class EnterpriseTest < ActiveSupport::TestCase | @@ -234,12 +234,12 @@ class EnterpriseTest < ActiveSupport::TestCase | ||
234 | assert enterprise.enable(person) | 234 | assert enterprise.enable(person) |
235 | end | 235 | end |
236 | 236 | ||
237 | - should 'list product categories full name' do | 237 | + should 'list product categories' do |
238 | subcategory = fast_create(ProductCategory, :name => 'Products subcategory', :parent_id => @product_category.id) | 238 | subcategory = fast_create(ProductCategory, :name => 'Products subcategory', :parent_id => @product_category.id) |
239 | ent = fast_create(Enterprise, :name => 'test ent', :identifier => 'test_ent') | 239 | ent = fast_create(Enterprise, :name => 'test ent', :identifier => 'test_ent') |
240 | p = ent.products.create!(:name => 'test prod', :product_category => subcategory) | 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 | end | 243 | end |
244 | 244 | ||
245 | should 'not create a products block for enterprise if environment do not let' do | 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,4 +36,29 @@ class ProductCategoryTest < ActiveSupport::TestCase | ||
36 | assert_equal [c11], ProductCategory.menu_categories(c1, nil) | 36 | assert_equal [c11], ProductCategory.menu_categories(c1, nil) |
37 | end | 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 | end | 64 | end |
test/unit/product_test.rb
@@ -89,21 +89,6 @@ class ProductTest < ActiveSupport::TestCase | @@ -89,21 +89,6 @@ class ProductTest < ActiveSupport::TestCase | ||
89 | end | 89 | end |
90 | end | 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 | should 'have same lat and lng of its enterprise' do | 92 | should 'have same lat and lng of its enterprise' do |
108 | ent = fast_create(Enterprise, :name => 'test enterprise', :identifier => 'test_enterprise', :lat => 30.0, :lng => 30.0) | 93 | ent = fast_create(Enterprise, :name => 'test enterprise', :identifier => 'test_enterprise', :lat => 30.0, :lng => 30.0) |
109 | prod = ent.products.create!(:name => 'test product', :product_category => @product_category) | 94 | prod = ent.products.create!(:name => 'test product', :product_category => @product_category) |