is_msfte_searchable 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: