is_msfte_searchable 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,6 +3,7 @@ require 'active_record'
3
3
  require 'is_msfte_searchable/active_record_extension'
4
4
  require 'is_msfte_searchable/active_record_mixin'
5
5
  require 'is_msfte_searchable/arel_mixin'
6
+ require 'is_msfte_searchable/no_full_text_index_error'
6
7
  require 'is_msfte_searchable/version'
7
8
 
8
9
  ActiveRecord::Base.send :include, IsMsfteSearchable::ActiveRecordExtension
@@ -16,6 +16,35 @@ module IsMsfteSearchable
16
16
  include IsMsfteSearchable::ActiveRecordMixin
17
17
  include IsMsfteSearchable::ArelMixin
18
18
  end
19
+
20
+ def msfte_column_indexed?(column)
21
+ # Any column in this table full-text indexed?
22
+ sql_statement =
23
+ <<-stmt
24
+ select count(*)
25
+ from sys.fulltext_index_columns fic
26
+ inner join sys.columns c
27
+ on c.[object_id] = fic.[object_id]
28
+ and c.[column_id] = fic.[column_id]
29
+ where OBJECT_ID('#{table_name}') = fic.[object_id]
30
+ stmt
31
+
32
+ # Search for an actual column name if given.
33
+ sql_statement << " and name = '#{column}'" unless column == '*'
34
+
35
+ value = connection.select_value(sql_statement)
36
+ value.to_i == 1
37
+ end
38
+
39
+ # Query the object properties of the current table.
40
+ # TableFulltextPendingChanges returns the number of pending changes.
41
+ # See: http://technet.microsoft.com/en-us/library/ms188390.aspx
42
+ def msfte_pending_changes?
43
+ sql_statement =
44
+ %|select cast(OBJECTPROPERTYEX(OBJECT_ID('#{table_name}'), 'TableFulltextPendingChanges') as varchar(10))|
45
+ value = connection.select_value(sql_statement)
46
+ value.to_i != 0
47
+ end
19
48
  end
20
49
  end
21
50
  end
@@ -27,20 +27,17 @@ module IsMsfteSearchable
27
27
  msfte_columns.each do |c|
28
28
  scope "msfte_#{c}_with_any".to_sym, lambda { |query|
29
29
  return {} if query.blank?
30
- return msfte_like_bailout(c, query) if Rails.env.test?
31
- msfte_contains(msfte_search_string(query, 'OR'), :column => c)
30
+ msfte_try_contains(msfte_search_string(query, 'OR'), :column => c)
32
31
  }
33
32
 
34
33
  scope "msfte_#{c}_with_all".to_sym, lambda { |query|
35
34
  return {} if query.blank?
36
- return msfte_like_bailout(c, query) if Rails.env.test?
37
- msfte_contains(msfte_search_string(query, 'AND'), :column => c)
35
+ msfte_try_contains(msfte_search_string(query, 'AND'), :column => c)
38
36
  }
39
37
 
40
38
  scope "msfte_#{c}_with_booleans".to_sym, lambda { |query|
41
39
  return {} if query.blank?
42
- return msfte_like_bailout(c, query) if Rails.env.test?
43
- msfte_contains(query, :column => c, :quote => true)
40
+ msfte_try_contains(query, :column => c, :quote => true)
44
41
  }
45
42
  end
46
43
  end
@@ -49,6 +46,18 @@ module IsMsfteSearchable
49
46
  module ClassMethods
50
47
  private
51
48
 
49
+ def msfte_try_contains(query, options={})
50
+ column = options.fetch(:column, '*')
51
+ if msfte_column_indexed?(column)
52
+ until !msfte_pending_changes? do
53
+ sleep 1
54
+ end
55
+ msfte_contains(query, options)
56
+ else
57
+ raise NoFullTextIndexError, "column '#{column}' is not full-text indexed"
58
+ end
59
+ end
60
+
52
61
  def msfte_like_bailout(column, query)
53
62
  { :conditions => "#{table_name}.#{column} LIKE '%#{msfte_quote(query)}%'" }
54
63
  end
@@ -0,0 +1,4 @@
1
+ module IsMsfteSearchable
2
+ class NoFullTextIndexError < ArgumentError
3
+ end
4
+ end
@@ -1,3 +1,3 @@
1
1
  module IsMsfteSearchable
2
- VERSION = '3.2.0'
2
+ VERSION = '3.3.0'
3
3
  end
@@ -5,6 +5,10 @@ describe IsMsfteSearchable::ActiveRecordExtension do
5
5
  ActiveRecord::Base.must_respond_to(:is_msfte_searchable)
6
6
  end
7
7
 
8
+ it "extends ActiveRecord::Base with an msfte_pending_changes? method" do
9
+ ActiveRecord::Base.must_respond_to(:msfte_pending_changes?)
10
+ end
11
+
8
12
  class FakeActiveRecord
9
13
  def self.table_name
10
14
  'people'
@@ -1,17 +1,5 @@
1
1
  require 'helper'
2
2
 
3
- class Rails
4
- class Env
5
- def self.test?
6
- false
7
- end
8
- end
9
-
10
- def self.env
11
- Env
12
- end
13
- end
14
-
15
3
  ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
16
4
 
17
5
  ActiveRecord::Base.class_eval do
@@ -24,6 +12,14 @@ end
24
12
 
25
13
  class Person < ActiveRecord::Base
26
14
  is_msfte_searchable(:columns => %w(name))
15
+
16
+ def self.msfte_column_indexed?(column)
17
+ true
18
+ end
19
+
20
+ def self.msfte_pending_changes?
21
+ false
22
+ end
27
23
  end
28
24
 
29
25
  # The SQL generated is courtesy of the sqlite adapter, so the whitespace and
@@ -121,11 +117,11 @@ describe IsMsfteSearchable::ArelMixin do
121
117
  )
122
118
  end
123
119
 
124
- it "returns a scope using a LIKE query when Rails.env.test?" do
125
- Rails.env.stubs(:test?).returns(true)
126
- Person.msfte_name_with_any('foo bar').to_sql.must_equal(
127
- %{SELECT "people".* FROM "people" WHERE (people.name LIKE '%foo bar%')}
128
- )
120
+ it "raises an exception if the searched column is not indexed" do
121
+ Person.stubs(:msfte_column_indexed?).returns(false)
122
+ Proc.new do
123
+ Person.msfte_name_with_any('foo bar')
124
+ end.must_raise IsMsfteSearchable::NoFullTextIndexError
129
125
  end
130
126
  end
131
127
 
@@ -146,11 +142,11 @@ describe IsMsfteSearchable::ArelMixin do
146
142
  )
147
143
  end
148
144
 
149
- it "returns a scope using a LIKE query when Rails.env.test?" do
150
- Rails.env.stubs(:test?).returns(true)
151
- Person.msfte_name_with_all('foo bar').to_sql.must_equal(
152
- %{SELECT "people".* FROM "people" WHERE (people.name LIKE '%foo bar%')}
153
- )
145
+ it "raises an exception if the searched column is not indexed" do
146
+ Person.stubs(:msfte_column_indexed?).returns(false)
147
+ Proc.new do
148
+ Person.msfte_name_with_all('foo bar')
149
+ end.must_raise IsMsfteSearchable::NoFullTextIndexError
154
150
  end
155
151
  end
156
152
 
@@ -171,13 +167,12 @@ describe IsMsfteSearchable::ArelMixin do
171
167
  )
172
168
  end
173
169
 
174
- it "returns a scope using a LIKE query when Rails.env.test?" do
175
- Rails.env.stubs(:test?).returns(true)
176
- Person.msfte_name_with_booleans('foo bar').to_sql.must_equal(
177
- %{SELECT "people".* FROM "people" WHERE (people.name LIKE '%foo bar%')}
178
- )
170
+ it "raises an exception if the searched column is not indexed" do
171
+ Person.stubs(:msfte_column_indexed?).returns(false)
172
+ Proc.new do
173
+ Person.msfte_name_with_any('foo bar')
174
+ end.must_raise IsMsfteSearchable::NoFullTextIndexError
179
175
  end
180
176
  end
181
177
  end
182
-
183
178
  end
metadata CHANGED
@@ -1,129 +1,121 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: is_msfte_searchable
3
- version: !ruby/object:Gem::Version
4
- hash: 15
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.3.0
5
5
  prerelease:
6
- segments:
7
- - 3
8
- - 2
9
- - 0
10
- version: 3.2.0
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Ken Collins
14
9
  - Donald Ball
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2012-03-14 00:00:00 Z
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
13
+ date: 2012-09-18 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
22
16
  name: activerecord
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
25
18
  none: false
26
- requirements:
19
+ requirements:
27
20
  - - ~>
28
- - !ruby/object:Gem::Version
29
- hash: 15
30
- segments:
31
- - 3
32
- - 2
33
- - 0
21
+ - !ruby/object:Gem::Version
34
22
  version: 3.2.0
35
23
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: activesupport
39
24
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: 3.2.0
31
+ - !ruby/object:Gem::Dependency
32
+ name: activesupport
33
+ requirement: !ruby/object:Gem::Requirement
41
34
  none: false
42
- requirements:
35
+ requirements:
43
36
  - - ~>
44
- - !ruby/object:Gem::Version
45
- hash: 15
46
- segments:
47
- - 3
48
- - 2
49
- - 0
37
+ - !ruby/object:Gem::Version
50
38
  version: 3.2.0
51
39
  type: :runtime
52
- version_requirements: *id002
53
- - !ruby/object:Gem::Dependency
54
- name: rake
55
40
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
41
+ version_requirements: !ruby/object:Gem::Requirement
57
42
  none: false
58
- requirements:
43
+ requirements:
59
44
  - - ~>
60
- - !ruby/object:Gem::Version
61
- hash: 63
62
- segments:
63
- - 0
64
- - 9
65
- - 2
45
+ - !ruby/object:Gem::Version
46
+ version: 3.2.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
66
54
  version: 0.9.2
67
55
  type: :development
68
- version_requirements: *id003
69
- - !ruby/object:Gem::Dependency
70
- name: minitest
71
56
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::Requirement
57
+ version_requirements: !ruby/object:Gem::Requirement
73
58
  none: false
74
- requirements:
59
+ requirements:
75
60
  - - ~>
76
- - !ruby/object:Gem::Version
77
- hash: 45
78
- segments:
79
- - 2
80
- - 8
81
- - 1
61
+ - !ruby/object:Gem::Version
62
+ version: 0.9.2
63
+ - !ruby/object:Gem::Dependency
64
+ name: minitest
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
82
70
  version: 2.8.1
83
71
  type: :development
84
- version_requirements: *id004
85
- - !ruby/object:Gem::Dependency
86
- name: mocha
87
72
  prerelease: false
88
- requirement: &id005 !ruby/object:Gem::Requirement
73
+ version_requirements: !ruby/object:Gem::Requirement
89
74
  none: false
90
- requirements:
75
+ requirements:
91
76
  - - ~>
92
- - !ruby/object:Gem::Version
93
- hash: 61
94
- segments:
95
- - 0
96
- - 10
97
- - 5
77
+ - !ruby/object:Gem::Version
78
+ version: 2.8.1
79
+ - !ruby/object:Gem::Dependency
80
+ name: mocha
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ~>
85
+ - !ruby/object:Gem::Version
98
86
  version: 0.10.5
99
87
  type: :development
100
- version_requirements: *id005
101
- - !ruby/object:Gem::Dependency
102
- name: sqlite3
103
88
  prerelease: false
104
- requirement: &id006 !ruby/object:Gem::Requirement
89
+ version_requirements: !ruby/object:Gem::Requirement
105
90
  none: false
106
- requirements:
91
+ requirements:
107
92
  - - ~>
108
- - !ruby/object:Gem::Version
109
- hash: 9
110
- segments:
111
- - 1
112
- - 3
113
- version: "1.3"
93
+ - !ruby/object:Gem::Version
94
+ version: 0.10.5
95
+ - !ruby/object:Gem::Dependency
96
+ name: sqlite3
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: '1.3'
114
103
  type: :development
115
- version_requirements: *id006
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '1.3'
116
111
  description: ActiveRecord extensions for Microsoft SQL Server full-text index
117
- email:
112
+ email:
118
113
  - ken@metaskills.net
119
114
  - donald.ball@gmail.com
120
115
  executables: []
121
-
122
116
  extensions: []
123
-
124
117
  extra_rdoc_files: []
125
-
126
- files:
118
+ files:
127
119
  - .gitignore
128
120
  - CHANGELOG.md
129
121
  - Gemfile
@@ -134,6 +126,7 @@ files:
134
126
  - lib/is_msfte_searchable/active_record_extension.rb
135
127
  - lib/is_msfte_searchable/active_record_mixin.rb
136
128
  - lib/is_msfte_searchable/arel_mixin.rb
129
+ - lib/is_msfte_searchable/no_full_text_index_error.rb
137
130
  - lib/is_msfte_searchable/version.rb
138
131
  - test/active_record_extension_test.rb
139
132
  - test/active_record_mixin_test.rb
@@ -141,39 +134,32 @@ files:
141
134
  - test/helper.rb
142
135
  homepage: http://github.com/Decisiv/is_msfte_searchable/
143
136
  licenses: []
144
-
145
137
  post_install_message:
146
- rdoc_options:
138
+ rdoc_options:
147
139
  - --charset=UTF-8
148
- require_paths:
140
+ require_paths:
149
141
  - lib
150
- required_ruby_version: !ruby/object:Gem::Requirement
142
+ required_ruby_version: !ruby/object:Gem::Requirement
151
143
  none: false
152
- requirements:
153
- - - ">="
154
- - !ruby/object:Gem::Version
155
- hash: 3
156
- segments:
157
- - 0
158
- version: "0"
159
- required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ! '>='
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
160
149
  none: false
161
- requirements:
162
- - - ">="
163
- - !ruby/object:Gem::Version
164
- hash: 3
165
- segments:
166
- - 0
167
- version: "0"
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
168
154
  requirements: []
169
-
170
155
  rubyforge_project:
171
- rubygems_version: 1.8.17
156
+ rubygems_version: 1.8.24
172
157
  signing_key:
173
158
  specification_version: 3
174
159
  summary: ActiveRecord extensions for Microsoft SQL Server full-text index
175
- test_files:
160
+ test_files:
176
161
  - test/active_record_extension_test.rb
177
162
  - test/active_record_mixin_test.rb
178
163
  - test/arel_mixin_test.rb
179
164
  - test/helper.rb
165
+ has_rdoc: