wvanbergen-scoped_search 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,13 @@
1
+ = Changelog for scoped_search
2
+
3
+ The following changes were incorporated in each scoped_search release.
4
+
5
+ == scoped_search 0.3.0
6
+ - Detection of column types so they can be handled properly
7
+ - Date based queries supported on date and time fields
8
+
9
+ == scoped_search 0.2.0
10
+ - OR keyword supported in query language
11
+
12
+ == scoped_search 0.1.0
13
+ - Initial version
@@ -1,12 +1,10 @@
1
- = scoped_search[http://github.com/wvanbergen/scoped_search/tree/master]
1
+ = scoped_search
2
2
 
3
3
  This simple plugin will make it easy to search your ActiveRecord models. Searching is performed using a query string, which should be passed to the named_scope *search_for* that uses SQL %LIKE% conditions for searching (ILIKE for Postgres). You can specify what fields should be used for searching.
4
4
 
5
-
6
5
  == Installing
7
6
 
8
- gem install wvanbergen-scoped_search
9
-
7
+ gem install wvanbergen-scoped_search -s http://gems.github.com
10
8
 
11
9
  == Usage
12
10
 
@@ -54,6 +52,13 @@ projects that are accessible by a given user.
54
52
  Project.accessible_by(current_user).search_for(params[:q]).paginate(:page => params[:page], :include => :tasks)
55
53
 
56
54
 
55
+ == Additional resources
56
+
57
+ * Source code: http://github.com/wvanbergen/scoped_search
58
+ * Project wiki: http://wiki.github.com/wvanbergen/scoped_search
59
+ * RDoc documentation: http://wvanbergen.github.com/scoped_search
60
+ * wvanbergen's blog posts: http://techblog.floorplanner.com/tag/scoped_search/
61
+
57
62
  == License
58
63
 
59
64
  This plugin is released under the MIT license. Please contact (willem AT vanbergen DOT org) if you have any suggestions or remarks.
data/Rakefile CHANGED
@@ -1,25 +1,43 @@
1
- require 'rubygems'
2
- require 'rake/rdoctask'
3
-
4
1
  Dir['tasks/*.rake'].each { |file| load(file) }
5
2
 
6
- desc 'Default: run unit tests.'
7
3
  task :default => [:test]
8
4
 
9
- ##############################################
10
- # Build RDocs
11
- ##############################################
12
- desc 'Generate documentation for the acts_as_callback_logger plugin.'
13
- Rake::RDocTask.new do |rdoc|
14
- rdoc.rdoc_dir = 'doc/html'
15
- rdoc.title = 'scoped_search'
16
- rdoc.options << '--line-numbers' << '--inline-source'
17
- rdoc.main = 'README'
18
- rdoc.rdoc_files.include('README',
19
- 'CHANGELOG',
20
- 'LICENSE',
21
- 'TODO',
22
- 'lib/')
23
- end
24
- ##############################################
5
+ namespace :test do
6
+
7
+ desc "Run tests for all configured databases in test/database.yml"
8
+ task :all do
9
+
10
+ databases = YAML.load(File.read(File.dirname(__FILE__) + '/test/database.yml'))
11
+ databases.each do |database, config|
12
+ puts "\nRunning testsuite on #{database} database...\n\n"
13
+ sh "rake test DATABASE=#{database}"
14
+ end
15
+ puts "\nFinished testing for all configured databases!"
16
+ puts "(Configure databases by adjusting test/database.yml)"
17
+ end
18
+
19
+ task :single do
20
+ database = ENV['DATABASE'] || 'sqlite3'
21
+ puts "Running testsuite on #{database} database...\n"
22
+ sh "rake test DATABASE=#{database}"
23
+ end
24
+
25
+ desc "Run tests on SQLite3 database"
26
+ task :sqlite3 do
27
+ puts "Running testsuite on SQLite3 database...\n"
28
+ sh 'rake test DATABASE=sqlite3'
29
+ end
30
+
31
+ desc "Run tests on MySQL database"
32
+ task :mysql do
33
+ puts "Running testsuite on MySQL database...\n"
34
+ sh 'rake test DATABASE=mysql'
35
+ end
36
+
37
+ desc "Run tests on PostgrSQL database"
38
+ task :postgresql do
39
+ puts "Running testsuite on PostgreSQL database...\n"
40
+ sh 'rake test DATABASE=postgresql'
41
+ end
25
42
 
43
+ end
data/TODO.rdoc ADDED
@@ -0,0 +1,6 @@
1
+ = TODO items for scoped_search
2
+
3
+ Contact me at my GitHub account (http://github.com/wvanbergen) if you want to help out.
4
+
5
+ == Documentation & testing
6
+ - Add rdoc and comments to code
@@ -26,17 +26,88 @@ module Rake
26
26
  desc "Updates the file lists for this gem"
27
27
  task(:manifest) { manifest_task }
28
28
 
29
- desc "Builds a .gem package for #{@name}"
30
- task(:build) { build_task }
29
+ desc "Releases a new version of #{@name}"
30
+ task(:build => [:manifest]) { build_task }
31
+
31
32
 
33
+ release_dependencies = [:check_clean_master_branch, :version, :build, :create_tag]
34
+ release_dependencies.push 'doc:publish' if has_rdoc?
35
+ release_dependencies.unshift 'test' if has_tests?
36
+ release_dependencies.unshift 'spec' if has_specs?
37
+
32
38
  desc "Releases a new version of #{@name}"
33
- task(:release) { release_task }
39
+ task(:release => release_dependencies) { release_task }
40
+
41
+ # helper task for releasing
42
+ task(:check_clean_master_branch) { verify_clean_status('master') }
43
+ task(:check_version) { verify_version(ENV['VERSION'] || @specification.version) }
44
+ task(:version => [:check_version]) { set_gem_version! }
45
+ task(:create_tag) { create_version_tag! }
46
+ end
47
+
48
+ # Register RDoc tasks
49
+ if has_rdoc?
50
+ require 'rake/rdoctask'
34
51
 
35
- end
52
+ namespace(:doc) do
53
+ desc 'Generate documentation for request-log-analyzer'
54
+ Rake::RDocTask.new(:compile) do |rdoc|
55
+ rdoc.rdoc_dir = 'doc'
56
+ rdoc.title = @name
57
+ rdoc.options += @specification.rdoc_options
58
+ rdoc.rdoc_files.include(@specification.extra_rdoc_files)
59
+ rdoc.rdoc_files.include('lib/**/*.rb')
60
+ end
61
+
62
+ desc "Publish RDoc files for #{@name} to Github"
63
+ task(:publish => :compile) do
64
+ sh 'git checkout gh-pages'
65
+ sh 'git pull origin gh-pages'
66
+ sh 'cp -rf doc/* .'
67
+ sh "git commit -am \"Publishing newest RDoc documentation for #{@name}\""
68
+ sh "git push origin gh-pages"
69
+ sh "git checkout master"
70
+ end
71
+ end
72
+ end
73
+
74
+ # Setup :spec task if RSpec files exist
75
+ if has_specs?
76
+ require 'spec/rake/spectask'
77
+
78
+ desc "Run all specs for #{@name}"
79
+ Spec::Rake::SpecTask.new(:spec) do |t|
80
+ t.spec_files = FileList['spec/**/*_spec.rb']
81
+ end
82
+ end
83
+
84
+ # Setup :test task if unit test files exist
85
+ if has_tests?
86
+ require 'rake/testtask'
87
+
88
+ desc "Run all unit tests for #{@name}"
89
+ Rake::TestTask.new(:test) do |t|
90
+ t.pattern = 'test/**/*_test.rb'
91
+ t.verbose = true
92
+ t.libs << 'test'
93
+ end
94
+ end
36
95
  end
37
96
 
38
97
  protected
39
98
 
99
+ def has_rdoc?
100
+ @specification.has_rdoc
101
+ end
102
+
103
+ def has_specs?
104
+ Dir['spec/**/*_spec.rb'].any?
105
+ end
106
+
107
+ def has_tests?
108
+ Dir['test/**/*_test.rb'].any?
109
+ end
110
+
40
111
  def reload_gemspec!
41
112
  raise "No gemspec file found!" if gemspec_file.nil?
42
113
  spec = File.read(gemspec_file)
@@ -110,6 +181,12 @@ module Rake
110
181
  newest_version = run_command('git tag').map { |tag| tag.split(name + '-').last }.compact.map { |v| Gem::Version.new(v) }.max
111
182
  raise "This version number (#{new_version}) is not higher than the highest tagged version (#{newest_version})" if !newest_version.nil? && newest_version >= Gem::Version.new(new_version.to_s)
112
183
  end
184
+
185
+ def set_gem_version!
186
+ # update gemspec file
187
+ self.gemspec_version = ENV['VERSION'] if Gem::Version.correct?(ENV['VERSION'])
188
+ self.gemspec_date = Date.today
189
+ end
113
190
 
114
191
  def manifest_task
115
192
  verify_current_branch('master')
@@ -153,19 +230,19 @@ module Rake
153
230
  sh "gem uninstall #{name}"
154
231
  end
155
232
 
156
- def release_task
157
- verify_clean_status('master')
158
- verify_version(ENV['VERSION'] || @specification.version)
159
-
160
- # update gemspec file
161
- self.gemspec_version = ENV['VERSION'] if Gem::Version.correct?(ENV['VERSION'])
162
- self.gemspec_date = Date.today
163
- manifest_task
233
+ def create_version_tag!
234
+ # commit the gemspec file
164
235
  git_commit_file(gemspec_file, "Updated #{gemspec_file} for release of version #{@specification.version}") if git_modified?(gemspec_file)
165
236
 
166
237
  # create tag and push changes
167
238
  git_create_tag("#{@name}-#{@specification.version}", "Tagged version #{@specification.version}")
168
- git_push('origin', 'master', [:tags])
239
+ git_push('origin', 'master', [:tags])
240
+ end
241
+
242
+ def release_task
243
+ puts
244
+ puts '------------------------------------------------------------'
245
+ puts "Released #{@name} - version #{@specification.version}"
169
246
  end
170
247
  end
171
248
  end
data/test/database.yml ADDED
@@ -0,0 +1,17 @@
1
+ sqlite3:
2
+ adapter: "sqlite3"
3
+ database: ":memory:"
4
+
5
+ mysql:
6
+ adapter: "mysql"
7
+ host: "localhost"
8
+ user: "root"
9
+ password:
10
+ database: "scoped_search_test"
11
+
12
+ postgresql:
13
+ adapter: "postgresql"
14
+ host: "localhost"
15
+ username: "sstest"
16
+ password: "sstest"
17
+ database: "scoped_search_test"
@@ -0,0 +1,52 @@
1
+ require "#{File.dirname(__FILE__)}/../test_helper.rb"
2
+
3
+ class ScopedSearch::Test::API < Test::Unit::TestCase
4
+
5
+ def self.const_missing(const)
6
+ ScopedSearch::Test::Models.const_get(const)
7
+ end
8
+
9
+ def setup
10
+ ScopedSearch::Test::establish_connection
11
+ ScopedSearch::Test::DatabaseSchema.up
12
+ end
13
+
14
+ def teardown
15
+ ScopedSearch::Test::DatabaseSchema.down
16
+ end
17
+
18
+ def test_enabling
19
+ assert !Foo.respond_to?(:search_for)
20
+ Foo.searchable_on :string_field, :text_field, :date_field
21
+ assert Foo.respond_to?(:search_for)
22
+
23
+ assert_equal ActiveRecord::NamedScope::Scope, Foo.search_for('test').class
24
+ end
25
+
26
+ def test_search_only_fields
27
+ Foo.searchable_on :only => [:string_field, :text_field, :date_field]
28
+ assert Foo.respond_to?(:search_for)
29
+ assert_equal Foo.scoped_search_fields.size, 3
30
+ assert Foo.scoped_search_fields.include?(:string_field)
31
+ assert Foo.scoped_search_fields.include?(:text_field)
32
+ assert Foo.scoped_search_fields.include?(:date_field)
33
+ end
34
+
35
+ def test_search_except_fields
36
+ Foo.searchable_on :except => [:id, :ignored_field, :created_at, :updated_at]
37
+ assert Foo.respond_to?(:search_for)
38
+ assert_equal Foo.scoped_search_fields.size, 3
39
+ assert Foo.scoped_search_fields.include?(:string_field)
40
+ assert Foo.scoped_search_fields.include?(:text_field)
41
+ assert Foo.scoped_search_fields.include?(:date_field)
42
+ end
43
+
44
+ def test_search_with_only_and_except
45
+ # :except should be ignored if :only is specified.
46
+ Foo.searchable_on({:only => [:text_field], :except => [:text_field]})
47
+ assert Foo.respond_to?(:search_for)
48
+ assert_equal Foo.scoped_search_fields.size, 1
49
+ assert Foo.scoped_search_fields.include?(:text_field), ':except should be ignored if :only is specified'
50
+ end
51
+
52
+ end
@@ -0,0 +1,148 @@
1
+ module ScopedSearch::Test::Models
2
+
3
+ class Foo < ActiveRecord::Base
4
+ def self.create_corpus!
5
+ create!(:string_field => "Programmer 123", :text_field => nil, :ignored_field => "123456", :date_field => '2000-01-01')
6
+ create!(:string_field => "Jim", :text_field => "Henson", :ignored_field => "123456a", :date_field => '2001-04-15')
7
+ create!(:string_field => "Jim", :text_field => "Bush", :ignored_field => "123456b", :date_field => '2001-04-17')
8
+ create!(:string_field => "Wes", :text_field => "Hays", :ignored_field => "123456c", :date_field => '1980-09-27')
9
+ create!(:string_field => "Bob", :text_field => "Hays", :ignored_field => "123456d", :date_field => '2002-11-09')
10
+ create!(:string_field => "Dogs", :text_field => "Pit Bull", :ignored_field => "123456e", :date_field => '2002-12-26')
11
+ create!(:string_field => "Dogs", :text_field => "Eskimo", :ignored_field => "123456f", :date_field => '2003-03-19')
12
+ create!(:string_field => "Cows", :text_field => "Farms", :ignored_field => "123456g", :date_field => '2004-05-01')
13
+ create!(:string_field => "Hello World", :text_field => "Hello Moon", :ignored_field => "123456h", :date_field => '2004-07-11')
14
+ create!(:string_field => "Hello World", :text_field => "Goodnight Moon", :ignored_field => "123456i", :date_field => '2004-09-12')
15
+ create!(:string_field => "Happy Cow", :text_field => "Sad Cow", :ignored_field => "123456j", :date_field => '2005-02-05')
16
+ create!(:string_field => "Happy Frog", :text_field => "Sad Frog", :ignored_field => "123456k", :date_field => '2006-03-09')
17
+ create!(:string_field => "Excited Frog", :text_field => "Sad Frog", :ignored_field => "123456l", :date_field => '2006-07-15')
18
+ create!(:string_field => "Man made", :text_field => "Woman made", :ignored_field => "123456m", :date_field => '2007-06-13')
19
+ create!(:string_field => "Cat Toys", :text_field => "Frog Toys", :ignored_field => "123456n", :date_field => '2008-03-04')
20
+ create!(:string_field => "Happy Toys", :text_field => "Sad Toys", :ignored_field => "123456n", :date_field => '2008-05-12')
21
+
22
+ create!(:string_field => "My son was born on 7/15/2006 and weighed 5.5 lbs",
23
+ :text_field => "Sad Toys",
24
+ :ignored_field => "123456n",
25
+ :date_field => '2008-09-22')
26
+ end
27
+ end
28
+
29
+ class User < ActiveRecord::Base
30
+ belongs_to :group
31
+ belongs_to :address
32
+ has_many :notes
33
+ has_and_belongs_to_many :locations
34
+
35
+ has_many :offices, :dependent => :destroy
36
+ has_many :clients, :through => :offices
37
+
38
+ def self.create_corpus!
39
+ create!(:first_name => 'Willem', :last_name => 'Van Bergen', :login => 'wvanbergen', :group_id => 1, :address_id => 1)
40
+ create!(:first_name => 'Wes', :last_name => 'Hays', :login => 'weshays', :group_id => 1, :address_id => 2)
41
+ create!(:first_name => 'John', :last_name => 'Dell', :login => 'jdell', :group_id => 2, :address_id => 3)
42
+ create!(:first_name => 'Ray', :last_name => 'York', :login => 'ryork', :group_id => 3, :address_id => 4)
43
+ create!(:first_name => 'Anna', :last_name => 'Landis', :login => 'alandis', :group_id => 4, :address_id => 5)
44
+
45
+ user = self.find_by_first_name('Willem')
46
+ user.locations << ScopedSearch::Test::Models::Location.find_by_name('Office')
47
+
48
+ user = self.find_by_first_name('Wes')
49
+ user.locations << ScopedSearch::Test::Models::Location.find_by_name('Store')
50
+
51
+ user = self.find_by_first_name('John')
52
+ user.locations << ScopedSearch::Test::Models::Location.find_by_name('Office')
53
+
54
+ user = self.find_by_first_name('Ray')
55
+ user.locations << ScopedSearch::Test::Models::Location.find_by_name('Home')
56
+
57
+ user = self.find_by_first_name('Anna')
58
+ user.locations << ScopedSearch::Test::Models::Location.find_by_name('Beach')
59
+ end
60
+ end
61
+
62
+ class Client < ActiveRecord::Base
63
+ has_many :offices, :dependent => :destroy
64
+ has_many :users, :through => :offices
65
+ def self.create_corpus!
66
+ create!(:first_name => 'Bob', :last_name => 'Smith')
67
+ create!(:first_name => 'Sam', :last_name => 'Lovett')
68
+ create!(:first_name => 'Sally', :last_name => 'May')
69
+ create!(:first_name => 'Mary', :last_name => 'Smith')
70
+ create!(:first_name => 'Darren', :last_name => 'Johnson')
71
+ end
72
+ end
73
+
74
+ class Office < ActiveRecord::Base
75
+ belongs_to :client
76
+ belongs_to :user
77
+ def self.create_corpus!
78
+ create!(:name => 'California Office', :user_id => 1, :client_id => 1)
79
+ create!(:name => 'California Office', :user_id => 2, :client_id => 2)
80
+ create!(:name => 'California Office', :user_id => 3, :client_id => 3)
81
+ create!(:name => 'Reno Office', :user_id => 4, :client_id => 4)
82
+ create!(:name => 'Reno Office', :user_id => 5, :client_id => 5)
83
+ end
84
+ end
85
+
86
+ class Group < ActiveRecord::Base
87
+ has_many :users
88
+ def self.create_corpus!
89
+ create!(:name => 'System Administrator')
90
+ create!(:name => 'Software Managers')
91
+ create!(:name => 'Office Managers')
92
+ create!(:name => 'Accounting')
93
+ end
94
+ end
95
+
96
+ class Location < ActiveRecord::Base
97
+ has_and_belongs_to_many :users
98
+ def self.create_corpus!
99
+ create!(:name => 'Home')
100
+ create!(:name => 'Office')
101
+ create!(:name => 'Store')
102
+ create!(:name => 'Beach')
103
+ end
104
+ end
105
+
106
+ class Note < ActiveRecord::Base
107
+ belongs_to :user
108
+ def self.create_corpus!
109
+ wes = ScopedSearch::Test::Models::User.find_by_first_name('Wes')
110
+ john = ScopedSearch::Test::Models::User.find_by_first_name('John')
111
+
112
+ create!(:user_id => wes.id,
113
+ :title => 'Purchases',
114
+ :content => "1) Linksys Router. 2) Network Cable")
115
+
116
+ create!(:user_id => wes.id,
117
+ :title => 'Tasks',
118
+ :content => 'Clean my car, walk the dog and mow the yard buy milk')
119
+
120
+ create!(:user_id => wes.id,
121
+ :title => 'Grocery List',
122
+ :content => 'milk, gum, apples')
123
+
124
+ create!(:user_id => wes.id,
125
+ :title => 'Stocks to watch',
126
+ :content => 'MA, AAPL, V and SSO. Straddle MA at 200 with JAN 09 options')
127
+
128
+ create!(:user_id => john.id,
129
+ :title => 'Spec Tests',
130
+ :content => 'Spec Tests... Spec Tests... Spec Tests!!')
131
+
132
+ create!(:user_id => john.id,
133
+ :title => 'Things To Do',
134
+ :content => '1) Did I mention Spec Tests!!!, 2) Buy Linksys Router WRT160N')
135
+ end
136
+ end
137
+
138
+ class Address < ActiveRecord::Base
139
+ has_one :user
140
+ def self.create_corpus!
141
+ create!(:street => '800 Haskell St', :city => 'Reno', :state => 'NV', :postal_code => '89509')
142
+ create!(:street => '2499 Dorchester Rd', :city => 'Charleston', :state => 'SC', :postal_code => '29414')
143
+ create!(:street => '474 Mallard Way', :city => 'Fernley', :state => 'NV', :postal_code => '89408')
144
+ create!(:street => '1600 Montero Ct', :city => 'Sparks', :state => 'NV', :postal_code => '89434')
145
+ create!(:street => '200 4th St', :city => 'Sparks', :state => 'NV', :postal_code => '89434')
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,66 @@
1
+ ActiveRecord::Migration.verbose = false unless ENV.has_key?('DEBUG')
2
+
3
+ class ScopedSearch::Test::DatabaseSchema < ActiveRecord::Migration
4
+
5
+ def self.up
6
+
7
+ create_table :foos do |t|
8
+ t.string :string_field
9
+ t.text :text_field
10
+ t.string :ignored_field
11
+ t.date :date_field
12
+ t.timestamps
13
+ end
14
+
15
+ create_table :users do |t|
16
+ t.string :first_name, :last_name, :login
17
+ t.integer :group_id
18
+ t.integer :address_id
19
+ end
20
+
21
+ create_table :clients do |t|
22
+ t.string :first_name, :last_name
23
+ end
24
+
25
+ create_table :offices do |t|
26
+ t.string :name
27
+ t.integer :user_id, :client_id
28
+ end
29
+
30
+ create_table :groups do |t|
31
+ t.string :name
32
+ end
33
+
34
+ create_table :locations do |t|
35
+ t.string :name
36
+ end
37
+
38
+ create_table :locations_users, :id => false, :force => true do |t|
39
+ t.integer :user_id
40
+ t.integer :location_id
41
+ end
42
+
43
+ create_table :notes do |t|
44
+ t.string :title
45
+ t.text :content
46
+ t.integer :user_id
47
+ end
48
+
49
+ create_table :addresses do |t|
50
+ t.string :street, :city, :state, :postal_code
51
+ end
52
+ end
53
+
54
+ def self.down
55
+ drop_table :foos
56
+ drop_table :users
57
+ drop_table :clients
58
+ drop_table :offices
59
+ drop_table :groups
60
+ drop_table :locations
61
+ drop_table :locations_users
62
+ drop_table :notes
63
+ drop_table :addresses
64
+ end
65
+
66
+ end