diff --git a/app/controllers/admin/edit_template_controller.rb b/app/controllers/admin/edit_template_controller.rb
index ddd10df..d5f6d02 100644
--- a/app/controllers/admin/edit_template_controller.rb
+++ b/app/controllers/admin/edit_template_controller.rb
@@ -9,6 +9,7 @@ class EditTemplateController < AdminController
%w[
FavoriteLinks
ListBlock
+ SellersSearchBlock
]
end
diff --git a/app/controllers/admin/environment_design_controller.rb b/app/controllers/admin/environment_design_controller.rb
index 0661dee..54f5219 100644
--- a/app/controllers/admin/environment_design_controller.rb
+++ b/app/controllers/admin/environment_design_controller.rb
@@ -3,7 +3,7 @@ class EnvironmentDesignController < BoxOrganizerController
protect 'edit_environment_design', :environment
def available_blocks
- @available_blocks ||= [ LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock ]
+ @available_blocks ||= [ LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock ]
end
end
diff --git a/app/controllers/public/search_controller.rb b/app/controllers/public/search_controller.rb
index e0dc981..bc019a5 100644
--- a/app/controllers/public/search_controller.rb
+++ b/app/controllers/public/search_controller.rb
@@ -60,14 +60,24 @@ class SearchController < ApplicationController
# TODO don't hardcode like this >:-(
LIST_LIMIT = 20
+ def complete_region
+ @regions = Region.find(:all, :conditions => [ 'name like ? and lat is not null and lng is not null', '%' + params[:region][:name] + '%' ])
+ render :action => 'complete_region', :layout => false
+ end
+
def index
@query = params[:query] || ''
@filtered_query = remove_stop_words(@query)
+ @region = Region.find_by_name(params[:region][:name]) if params[:region]
@results = {}
@names = {}
SEARCH_IN.each do |key, description|
- @results[key] = @finder.find(key, @filtered_query) if @searching[key]
+ if [:enterprises, :people].include?(key) && @region
+ @results[key] = @finder.find(key, @filtered_query, :within => params[:radius], :region => @region.id) if @searching[key]
+ else
+ @results[key] = @finder.find(key, @filtered_query) if @searching[key]
+ end
@names[key] = gettext(description)
end
end
@@ -122,16 +132,20 @@ class SearchController < ApplicationController
end
def sellers
+ # FIXME use a better select for category
@categories = ProductCategory.find(:all)
@regions = Region.find(:all).select{|r|r.lat && r.lng}
@product_category = ProductCategory.find(params[:category]) if params[:category]
@region = Region.find(params[:region]) if params[:region]
+
options = {}
- options.merge! :include => :products, :conditions => ['products.product_category_id = ?', @product_category.id] if @product_category
-
options.merge! :origin => [params[:lat].to_f, params[:long].to_f], :within => params[:radius] if !params[:lat].blank? && !params[:long].blank? && !params[:radius].blank?
-
options.merge! :origin => [@region.lat, @region.lng], :within => params[:radius] if !params[:region].blank? && !params[:radius].blank?
+ if @product_category
+ finder = CategoryFinder.new(@product_category)
+ product_ids = finder.find('products',nil)
+ options.merge! :include => :products, :conditions => ['products.id IN ?', product_ids ]
+ end
@enterprises = Enterprise.find(:all, options)
end
@@ -139,6 +153,7 @@ class SearchController < ApplicationController
#######################################################
def popup
+ @regions = Region.find(:all).select{|r|r.lat && r.lng}
render :action => 'popup', :layout => false
end
diff --git a/app/models/category_finder.rb b/app/models/category_finder.rb
index a61e5d8..d1db15b 100644
--- a/app/models/category_finder.rb
+++ b/app/models/category_finder.rb
@@ -7,8 +7,8 @@ class CategoryFinder
attr_reader :category_ids
- def find(asset, query)
- find_in_categorized(asset.to_s.singularize.camelize.constantize, query)
+ def find(asset, query, options={})
+ find_in_categorized(asset.to_s.singularize.camelize.constantize, query, options)
end
def recent(asset, limit = 10)
@@ -30,6 +30,13 @@ class CategoryFinder
protected
def find_in_categorized(klass, query, options={})
+ @region = Region.find_by_id(options.delete(:region)) if options.has_key?(:region)
+ if @region && options[:within]
+ options[:origin] = [@region.lat, @region.lng]
+ else
+ options.delete(:within)
+ end
+
if query.nil?
klass.find(:all, options_for_find(klass, options))
else
diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb
index 7ae25db..e7ebfdf 100644
--- a/app/models/enterprise.rb
+++ b/app/models/enterprise.rb
@@ -6,4 +6,10 @@ class Enterprise < Organization
has_many :products, :dependent => :destroy
+ extra_data_for_index :product_categories
+
+ def product_categories
+ products.map{|p| p.product_category.full_name.split('/') }.join(' ')
+ end
+
end
diff --git a/app/models/environment_finder.rb b/app/models/environment_finder.rb
index 1344c75..dd1eaa2 100644
--- a/app/models/environment_finder.rb
+++ b/app/models/environment_finder.rb
@@ -4,8 +4,14 @@ class EnvironmentFinder
@environment = env
end
- def find(asset, query)
- @environment.send(asset).find_by_contents(query)
+ def find(asset, query, options={})
+ @region = Region.find_by_id(options.delete(:region)) if options.has_key?(:region)
+ if @region && options[:within]
+ options[:origin] = [@region.lat, @region.lng]
+ else
+ options.delete(:within)
+ end
+ @environment.send(asset).find_by_contents(query, {}, options)
end
def recent(asset, limit = 10)
diff --git a/app/models/product.rb b/app/models/product.rb
index 60172f4..5876638 100644
--- a/app/models/product.rb
+++ b/app/models/product.rb
@@ -8,6 +8,14 @@ class Product < ActiveRecord::Base
after_update :save_image
+ after_create do |p|
+ p.enterprise.save if p.enterprise
+ end
+
+ after_update do |p|
+ p.enterprise.save if p.enterprise
+ end
+
acts_as_searchable :fields => [ :name, :description, :category_full_name ]
xss_terminate :only => [ :name, :description ]
diff --git a/app/models/profile.rb b/app/models/profile.rb
index cc67b66..3a39350 100644
--- a/app/models/profile.rb
+++ b/app/models/profile.rb
@@ -31,7 +31,19 @@ class Profile < ActiveRecord::Base
acts_as_having_boxes
- acts_as_searchable :fields => [ :name, :identifier ]
+ acts_as_searchable :fields => [ :name, :identifier, :extra_data_for_index ]
+
+ class_inheritable_accessor :extra_index_methods
+ self.extra_index_methods = []
+
+ def extra_data_for_index
+ self.class.extra_index_methods.map { |meth| meth.to_proc.call(self) }
+ end
+
+ def self.extra_data_for_index(sym = nil, &block)
+ self.extra_index_methods.push(sym) if sym
+ self.extra_index_methods.push(block) if block_given?
+ end
acts_as_having_settings :field => :data
diff --git a/app/models/sellers_search_block.rb b/app/models/sellers_search_block.rb
new file mode 100644
index 0000000..ef375f4
--- /dev/null
+++ b/app/models/sellers_search_block.rb
@@ -0,0 +1,14 @@
+class SellersSearchBlock < Block
+
+ def self.description
+ _('A search for enterprises by products selled and local')
+ end
+
+ def content
+ lambda do
+ @categories = ProductCategory.find(:all)
+ @regions = Region.find(:all).select{|r|r.lat && r.lng}
+ render :file => 'search/_sellers_form'
+ end
+ end
+end
diff --git a/app/views/search/_sellers_form.rhtml b/app/views/search/_sellers_form.rhtml
new file mode 100644
index 0000000..7c7da6d
--- /dev/null
+++ b/app/views/search/_sellers_form.rhtml
@@ -0,0 +1,9 @@
+<% form_tag({:controller => 'search', :action => 'index'}, {:method => 'get'}) do %>
+ <%= _('Category: ') %> <%= select_tag 'query', options_from_collection_for_select(@categories, :name, :name, @product_category), :width => 15 %>
+ <%= _('Distance: ') %> <%= text_field_tag 'radius' %>
+ <%= _('From: ') %> <%= text_field :region, :name, :id => 'search_region_block' %>
+
<%= render :partial => 'profile', :collection => @enterprises %>
diff --git a/public/stylesheets/common.css b/public/stylesheets/common.css
index 6ea966e..9c4be1a 100644
--- a/public/stylesheets/common.css
+++ b/public/stylesheets/common.css
@@ -230,6 +230,8 @@ table.cms-articles th, table.cms-articles td {
/* for fields with auto-completion */
div.auto-complete {
+ display: block;
+ float: none;
background: #729FCF;
border: 2px solid #204A87;
}
diff --git a/test/functional/search_controller_test.rb b/test/functional/search_controller_test.rb
index 8364fd9..932cbfa 100644
--- a/test/functional/search_controller_test.rb
+++ b/test/functional/search_controller_test.rb
@@ -397,6 +397,13 @@ class SearchControllerTest < Test::Unit::TestCase
assert_tag :tag => 'input', :attributes => { :type => 'submit', :name => 'search_whole_site_no' }
end
+ should 'display option to search within a given point and distance' do
+ get :popup
+
+ assert_tag :tag => 'input', :attributes => {:type => 'text', :name => 'radius'}
+ assert_tag :tag => 'input', :attributes => {:type => 'text', :name => 'region[name]'}
+ end
+
should 'search in whole site when told so' do
parent = Category.create!(:name => 'randomcat', :environment => Environment.default)
Category.create!(:name => 'randomchild', :environment => Environment.default, :parent => parent)
@@ -547,7 +554,7 @@ class SearchControllerTest < Test::Unit::TestCase
assert_tag :tag => 'h1', :content => /Search results for "a sample search" in "Child Category"/
end
- should 'search in categoty hierachy' do
+ should 'search in category hierachy' do
parent = Category.create!(:name => 'Parent Category', :environment => Environment.default)
child = Category.create!(:name => 'Child Category', :environment => Environment.default, :parent => parent)
@@ -760,78 +767,34 @@ class SearchControllerTest < Test::Unit::TestCase
assert_not_includes assigns(:results)[:comments], comment4
end
- should 'list all sellers' do
- ent1 = Enterprise.create!(:name => 'test1', :identifier => 'test1')
- ent2 = Enterprise.create!(:name => 'test2', :identifier => 'test2')
-
- get :sellers
-
- assert_includes assigns('enterprises'), ent1
- assert_includes assigns('enterprises'), ent2
- end
-
should 'find enterprise by product category' do
ent1 = Enterprise.create!(:name => 'test1', :identifier => 'test1')
- prod_cat = ProductCategory.create!(:name => 'pc-test', :environment => Environment.default)
+ prod_cat = ProductCategory.create!(:name => 'pctest', :environment => Environment.default)
prod = ent1.products.create!(:name => 'teste', :product_category => prod_cat)
ent2 = Enterprise.create!(:name => 'test2', :identifier => 'test2')
- get :sellers, :category => prod_cat.id
-
- assert_includes assigns('enterprises'), ent1
- assert_not_includes assigns('enterprises'), ent2
- end
-
- should 'find enterprise by origin and radius' do
- ent1 = Enterprise.create!(:name => 'test1', :identifier => 'test1', :lat => 45.0, :lng => 45.0)
- ent2 = Enterprise.create!(:name => 'test2', :identifier => 'test2', :lat => 30.0, :lng => 30.0)
-
- get :sellers, :lat => 45.0, :long => 45.0, :radius => 10
+ get :index, :query => prod_cat.name
- assert_includes assigns('enterprises'), ent1
- assert_not_includes assigns('enterprises'), ent2
+ assert_includes assigns('results')[:enterprises], ent1
+ assert_not_includes assigns('results')[:enterprises], ent2
end
- should 'find enterprise by an region with georeference' do
+ should 'find profiles by radius and region' do
region = Region.create!(:name => 'r-test', :environment => Environment.default, :lat => 45.0, :lng => 45.0)
- ent1 = Enterprise.create!(:name => 'test1', :identifier => 'test1', :lat => 45.0, :lng => 45.0)
- ent2 = Enterprise.create!(:name => 'test2', :identifier => 'test2', :lat => 30.0, :lng => 30.0)
+ ent1 = Enterprise.create!(:name => 'test 1', :identifier => 'test1', :lat => 45.0, :lng => 45.0)
+ p1 = create_user('test2').person
+ p1.name = 'test 2'; p1.lat = 45.0; p1.lng = 45.0; p1.save!
+ ent2 = Enterprise.create!(:name => 'test 3', :identifier => 'test3', :lat => 30.0, :lng => 30.0)
+ p2 = create_user('test4').person
+ p2.name = 'test 4'; p2.lat = 30.0; p2.lng = 30.0; p2.save!
- get :sellers, :region => region.id, :radius => 10
+ get :index, :region => { :name => region.name }, :radius => 10, :query => 'test'
- assert_includes assigns('enterprises'), ent1
- assert_not_includes assigns('enterprises'), ent2
- end
-
- should 'find enterprise by region and product category' do
- region = Region.create!(:name => 'r-test', :environment => Environment.default, :lat => 45.0, :lng => 45.0)
- ent1 = Enterprise.create!(:name => 'test1', :identifier => 'test1', :lat => 45.0, :lng => 45.0)
- prod_cat = ProductCategory.create!(:name => 'pc-test', :environment => Environment.default)
- prod = ent1.products.create!(:name => 'teste', :product_category => prod_cat)
-
- ent2 = Enterprise.create!(:name => 'test2', :identifier => 'test2', :lat => 30.0, :lng => 30.0)
-
- get :sellers, :region => region.id, :radius => 10, :category => prod_cat.id
-
- assert_includes assigns('enterprises'), ent1
- assert_not_includes assigns('enterprises'), ent2
- end
-
- should 'find enterprise by region and product category in brazilian portuguese' do
- region = Region.create!(:name => 'r-test', :environment => Environment.default, :lat => 45.0, :lng => 45.0)
- ent1 = Enterprise.create!(:name => 'test1', :identifier => 'test1', :lat => 45.0, :lng => 45.0)
- prod_cat = ProductCategory.create!(:name => 'pc-test', :environment => Environment.default)
- prod = ent1.products.create!(:name => 'teste', :product_category => prod_cat)
-
- ent2 = Enterprise.create!(:name => 'test2', :identifier => 'test2', :lat => 30.0, :lng => 30.0)
-
- assert_nothing_raised do
- get :sellers, :region => region.id, :radius => 10, :category => prod_cat.id, :lang => 'pt_BR'
- end
-
- assert_includes assigns('enterprises'), ent1
- assert_not_includes assigns('enterprises'), ent2
+ assert_includes assigns('results')[:enterprises], ent1
+ assert_not_includes assigns('results')[:enterprises], ent2
+ assert_includes assigns('results')[:people], p1
+ assert_not_includes assigns('results')[:people], p2
end
should 'not show term "Category:" before product category' do
@@ -852,4 +815,29 @@ class SearchControllerTest < Test::Unit::TestCase
assert_tag :tag => 'img', :attributes => { :src => /rails_thumb\.png/ }
end
+ should 'complete region name' do
+ r1 = Region.create!(:name => 'One region', :environment => Environment.default, :lat => 111.07, :lng => '88.9')
+ r2 = Region.create!(:name => 'Another region', :environment => Environment.default, :lat => 111.07, :lng => '88.9')
+
+ get :complete_region, :region => { :name => 'one' }
+ assert_includes assigns(:regions), r1
+ assert_tag :tag => 'ul', :descendant => { :tag => 'li', :content => 'One region' }
+ end
+
+ should 'render completion results without layout' do
+ get :complete_region, :region => { :name => 'test' }
+ assert_no_tag :tag => 'body'
+ end
+
+ should 'complete only georeferenced regions' do
+ r1 = Region.create!(:name => 'One region', :environment => Environment.default, :lat => 111.07, :lng => '88.9')
+ r2 = Region.create!(:name => 'Another region', :environment => Environment.default)
+
+ get :complete_region, :region => { :name => 'region' }
+ assert_includes assigns(:regions), r1
+ assert_tag :tag => 'ul', :descendant => { :tag => 'li', :content => r1.name }
+ assert_not_includes assigns(:regions), r2
+ assert_no_tag :tag => 'ul', :descendant => { :tag => 'li', :content => r2.name }
+ end
+
end
diff --git a/test/unit/category_finder_test.rb b/test/unit/category_finder_test.rb
index 785f989..def706b 100644
--- a/test/unit/category_finder_test.rb
+++ b/test/unit/category_finder_test.rb
@@ -252,4 +252,24 @@ class CategoryFinderTest < ActiveSupport::TestCase
assert_not_includes list, c2
end
+ should 'find person and enterprise by radius and region' do
+ finder = CategoryFinder.new(@category)
+
+ region = Region.create!(:name => 'r-test', :environment => Environment.default, :lat => 45.0, :lng => 45.0)
+ ent1 = Enterprise.create!(:name => 'test 1', :identifier => 'test1', :lat => 45.0, :lng => 45.0, :categories => [@category])
+ p1 = create_user('test2').person
+ p1.name = 'test 2'; p1.lat = 45.0; p1.lng = 45.0; p1.categories = [@category]; p1.save!
+ ent2 = Enterprise.create!(:name => 'test 3', :identifier => 'test3', :lat => 30.0, :lng => 30.0, :categories => [@category])
+ p2 = create_user('test4').person
+ p2.name = 'test 4'; p2.lat = 30.0; p2.lng = 30.0; p2.categories = [@category]; p2.save!
+
+ ents = finder.find(:enterprises, 'test', :within => 10, :region => region.id)
+ people = finder.find(:people, 'test', :within => 10, :region => region.id)
+
+ assert_includes ents, ent1
+ assert_not_includes ents, ent2
+ assert_includes people, p1
+ assert_not_includes people, p2
+ end
+
end
diff --git a/test/unit/enterprise_test.rb b/test/unit/enterprise_test.rb
index 4d1708c..9be6045 100644
--- a/test/unit/enterprise_test.rb
+++ b/test/unit/enterprise_test.rb
@@ -76,6 +76,33 @@ class EnterpriseTest < Test::Unit::TestCase
assert_equal 5, e.blocks.size
end
+ should 'be found in search for its product categories' do
+ ent1 = Enterprise.create!(:name => 'test1', :identifier => 'test1')
+ prod_cat = ProductCategory.create!(:name => 'pctest', :environment => Environment.default)
+ prod = ent1.products.create!(:name => 'teste', :product_category => prod_cat)
+
+ ent2 = Enterprise.create!(:name => 'test2', :identifier => 'test2')
+
+ result = Enterprise.find_by_contents(prod_cat.name)
+
+ assert_includes result, ent1
+ assert_not_includes result, ent2
+ end
+
+ should 'be found in search for its product categories hierarchy' do
+ ent1 = Enterprise.create!(:name => 'test1', :identifier => 'test1')
+ prod_cat = ProductCategory.create!(:name => 'pctest', :environment => Environment.default)
+ prod_child = ProductCategory.create!(:name => 'pchild', :environment => Environment.default, :parent => prod_cat)
+ prod = ent1.products.create!(:name => 'teste', :product_category => prod_child)
+
+ ent2 = Enterprise.create!(:name => 'test2', :identifier => 'test2')
+
+ result = Enterprise.find_by_contents(prod_cat.name)
+
+ assert_includes result, ent1
+ assert_not_includes result, ent2
+ end
+
should 'allow to add new members' do
o = Enterprise.create!(:name => 'my test profile', :identifier => 'mytestprofile')
p = create_user('mytestuser').person
diff --git a/test/unit/environment_finder_test.rb b/test/unit/environment_finder_test.rb
index fc7bef5..c749cf1 100644
--- a/test/unit/environment_finder_test.rb
+++ b/test/unit/environment_finder_test.rb
@@ -131,4 +131,24 @@ class EnvironmentFinderTest < ActiveSupport::TestCase
assert_not_includes found, ent2
end
+ should 'find person and enterprise by radius and region' do
+ finder = EnvironmentFinder.new(Environment.default)
+
+ region = Region.create!(:name => 'r-test', :environment => Environment.default, :lat => 45.0, :lng => 45.0)
+ ent1 = Enterprise.create!(:name => 'test 1', :identifier => 'test1', :lat => 45.0, :lng => 45.0)
+ p1 = create_user('test2').person
+ p1.name = 'test 2'; p1.lat = 45.0; p1.lng = 45.0; p1.save!
+ ent2 = Enterprise.create!(:name => 'test 3', :identifier => 'test3', :lat => 30.0, :lng => 30.0)
+ p2 = create_user('test4').person
+ p2.name = 'test 4'; p2.lat = 30.0; p2.lng = 30.0; p2.save!
+
+ ents = finder.find(:enterprises, 'test', :within => 10, :region => region.id)
+ people = finder.find(:people, 'test', :within => 10, :region => region.id)
+
+ assert_includes ents, ent1
+ assert_not_includes ents, ent2
+ assert_includes people, p1
+ assert_not_includes people, p2
+ end
+
end
diff --git a/test/unit/profile_test.rb b/test/unit/profile_test.rb
index 54ba070..d5271fe 100644
--- a/test/unit/profile_test.rb
+++ b/test/unit/profile_test.rb
@@ -69,7 +69,7 @@ class ProfileTest < Test::Unit::TestCase
p.identifier = 'other_profile'
end
end
-
+
should 'provide access to home page' do
profile = Profile.create!(:identifier => 'newprofile', :name => 'New Profile')
assert_kind_of Article, profile.home_page
@@ -87,7 +87,7 @@ class ProfileTest < Test::Unit::TestCase
def test_can_have_affiliated_people
pr = Profile.create(:name => 'composite_profile', :identifier => 'composite')
pe = User.create(:login => 'aff', :email => 'aff@pr.coop', :password => 'blih', :password_confirmation => 'blih').person
-
+
member_role = Role.new(:name => 'new_member_role')
assert member_role.save
assert pr.affiliate(pe, member_role)
@@ -164,7 +164,7 @@ class ProfileTest < Test::Unit::TestCase
assert_raise ActiveRecord::AssociationTypeMismatch do
profile.articles << 1
end
-
+
assert_nothing_raised do
profile.articles << Article.new(:name => 'testing article')
end
@@ -206,7 +206,7 @@ class ProfileTest < Test::Unit::TestCase
assert Profile.find_by_contents('small').include?(small)
assert Profile.find_by_contents('big').include?(big)
-
+
both = Profile.find_by_contents('profile testing')
assert both.include?(small)
assert both.include?(big)
@@ -229,7 +229,7 @@ class ProfileTest < Test::Unit::TestCase
profile_boxes = profile.boxes.size
profile_blocks = profile.blocks.size
-
+
assert profile_boxes > 0, 'profile should have some boxes'
assert profile_blocks > 0, 'profile should have some blocks'
@@ -488,6 +488,37 @@ class ProfileTest < Test::Unit::TestCase
assert c.display_info_to?(p)
end
+ should 'be able to add extra data for index' do
+ klass = Class.new(Profile)
+ klass.any_instance.expects(:random_method)
+ klass.extra_data_for_index :random_method
+
+ klass.new.extra_data_for_index
+ end
+
+ should 'be able to add a block as extra data for index' do
+ klass = Class.new(Profile)
+ result = mock
+ klass.extra_data_for_index do |obj|
+ result
+ end
+
+ assert_includes klass.new.extra_data_for_index, result
+ end
+
+ should 'actually index by results of extra_data_for_index' do
+
+ class ::TestingExtraDataForIndex < Profile
+ extra_data_for_index do |obj|
+ 'sample indexed text'
+ end
+ end
+
+ profile = TestingExtraDataForIndex.create!(:name => 'testprofile', :identifier => 'testprofile')
+
+ assert_includes TestingExtraDataForIndex.find_by_contents('sample'), profile
+ end
+
private
def assert_invalid_identifier(id)
diff --git a/test/unit/sellers_search_block_test.rb b/test/unit/sellers_search_block_test.rb
new file mode 100644
index 0000000..71c5aa9
--- /dev/null
+++ b/test/unit/sellers_search_block_test.rb
@@ -0,0 +1,8 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class SellersSearchBlockTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ def test_truth
+ assert true
+ end
+end
--
libgit2 0.21.2