case_insensitive_arel 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -2
- data/Gemfile.lock +19 -4
- data/README.rdoc +15 -1
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/case_insensitive_arel.gemspec +17 -14
- data/lib/case_insensitive_arel.rb +18 -2
- data/test/helper.rb +1 -1
- data/test/support/fake_record.rb +10 -11
- data/test/test_comparisons.rb +5 -0
- data/test/test_joins.rb +2 -2
- metadata +38 -24
data/Gemfile
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
gem "arel", "
|
4
|
-
gem 'activesupport', '
|
3
|
+
gem "arel", "~> 2.2.1"
|
4
|
+
gem 'activesupport', '~> 3.1.0'
|
5
5
|
|
6
6
|
group :development do
|
7
7
|
gem "shoulda", ">= 0"
|
8
8
|
gem "bundler", "~> 1.0.0"
|
9
9
|
gem "jeweler", "~> 1.5.2"
|
10
10
|
gem "rcov", ">= 0"
|
11
|
+
gem "pry"
|
11
12
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,24 +1,39 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activesupport (3.0
|
5
|
-
|
4
|
+
activesupport (3.1.0)
|
5
|
+
multi_json (~> 1.0)
|
6
|
+
arel (2.2.1)
|
7
|
+
coderay (0.9.8)
|
6
8
|
git (1.2.5)
|
7
9
|
jeweler (1.5.2)
|
8
10
|
bundler (~> 1.0.0)
|
9
11
|
git (>= 1.2.5)
|
10
12
|
rake
|
13
|
+
method_source (0.6.5)
|
14
|
+
ruby_parser (>= 2.0.5)
|
15
|
+
multi_json (1.0.3)
|
16
|
+
pry (0.9.5)
|
17
|
+
coderay (>= 0.9.8)
|
18
|
+
method_source (>= 0.6.5)
|
19
|
+
ruby_parser (>= 2.0.5)
|
20
|
+
slop (~> 2.1.0)
|
11
21
|
rake (0.8.7)
|
12
22
|
rcov (0.9.9)
|
23
|
+
ruby_parser (2.3.0)
|
24
|
+
sexp_processor (~> 3.0)
|
25
|
+
sexp_processor (3.0.6)
|
13
26
|
shoulda (2.11.3)
|
27
|
+
slop (2.1.0)
|
14
28
|
|
15
29
|
PLATFORMS
|
16
30
|
ruby
|
17
31
|
|
18
32
|
DEPENDENCIES
|
19
|
-
activesupport (
|
20
|
-
arel (
|
33
|
+
activesupport (~> 3.1.0)
|
34
|
+
arel (~> 2.2.1)
|
21
35
|
bundler (~> 1.0.0)
|
22
36
|
jeweler (~> 1.5.2)
|
37
|
+
pry
|
23
38
|
rcov
|
24
39
|
shoulda
|
data/README.rdoc
CHANGED
@@ -66,7 +66,7 @@ As an example, you could add this code to your app if you wanted to use lowercas
|
|
66
66
|
|
67
67
|
Due to the wrapping of column names with function calls, certain DBMS' optimizers may ignore indexes on those columns
|
68
68
|
that might otherwise be used for a query. If supported by your DBMS, you may be able to create a special index on
|
69
|
-
these columns to help out wih your query. As an example, Oracle supports
|
69
|
+
these columns to help out wih your query. As an example, Oracle supports function-based indexes.
|
70
70
|
|
71
71
|
For more information, please refer to your DBMS's documentation.
|
72
72
|
|
@@ -80,6 +80,20 @@ database adapters.
|
|
80
80
|
Rather than risk madness, I didn't even bother trying to make this work with custom SQL. Stick with Arel and there
|
81
81
|
won't be any issues.
|
82
82
|
|
83
|
+
=== Converting Numeric Values?
|
84
|
+
|
85
|
+
If Arel encounters a string value, it will convert it using the conversion_proc even if it contains a numeric
|
86
|
+
value being compared to a numeric column. In the typical case of looking up Rails' values that originate from the params
|
87
|
+
hash (e.g. <tt>params[:id]</tt> ) this could result in SQL like:
|
88
|
+
|
89
|
+
select * from "table" where "table"."id" = UPPER(3)
|
90
|
+
|
91
|
+
Since most DBMSes will implicitly convert the result of the function to a numeric, there should be no impact on the
|
92
|
+
query optimizer. If you absolutely must inhibit this function call from being generated, convert the string to a numeric
|
93
|
+
value before Arel sees it. e.g.:
|
94
|
+
|
95
|
+
Something.find(params[:id].to_i)
|
96
|
+
|
83
97
|
== Contributing
|
84
98
|
|
85
99
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
data/Rakefile
CHANGED
@@ -21,8 +21,8 @@ Jeweler::Tasks.new do |gem|
|
|
21
21
|
gem.authors = ["Steve Lamotte"]
|
22
22
|
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
23
|
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
-
gem.add_runtime_dependency 'arel', '>= 2.
|
25
|
-
gem.add_runtime_dependency 'activesupport', '>=
|
24
|
+
gem.add_runtime_dependency 'arel', '>= 2.2.1'
|
25
|
+
gem.add_runtime_dependency 'activesupport', '>= 3.1.0'
|
26
26
|
end
|
27
27
|
Jeweler::RubygemsDotOrgTasks.new
|
28
28
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{case_insensitive_arel}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Steve Lamotte"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-09-16}
|
13
13
|
s.description = %q{If you're using Oracle or another DBMS that has case-insensitive collation sequences, and you don't want to litter your database access code with case conversions, this gem is for you.}
|
14
14
|
s.email = %q{steve@lexor.ca}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -52,33 +52,36 @@ Gem::Specification.new do |s|
|
|
52
52
|
s.specification_version = 3
|
53
53
|
|
54
54
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
|
-
s.add_runtime_dependency(%q<arel>, ["
|
56
|
-
s.add_runtime_dependency(%q<activesupport>, ["
|
55
|
+
s.add_runtime_dependency(%q<arel>, ["~> 2.2.1"])
|
56
|
+
s.add_runtime_dependency(%q<activesupport>, ["~> 3.1.0"])
|
57
57
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
58
58
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
59
59
|
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
60
60
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
61
|
-
s.
|
62
|
-
s.add_runtime_dependency(%q<
|
61
|
+
s.add_development_dependency(%q<pry>, [">= 0"])
|
62
|
+
s.add_runtime_dependency(%q<arel>, [">= 2.2.1"])
|
63
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 3.1.0"])
|
63
64
|
else
|
64
|
-
s.add_dependency(%q<arel>, ["
|
65
|
-
s.add_dependency(%q<activesupport>, ["
|
65
|
+
s.add_dependency(%q<arel>, ["~> 2.2.1"])
|
66
|
+
s.add_dependency(%q<activesupport>, ["~> 3.1.0"])
|
66
67
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
67
68
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
68
69
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
69
70
|
s.add_dependency(%q<rcov>, [">= 0"])
|
70
|
-
s.add_dependency(%q<
|
71
|
-
s.add_dependency(%q<
|
71
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
72
|
+
s.add_dependency(%q<arel>, [">= 2.2.1"])
|
73
|
+
s.add_dependency(%q<activesupport>, [">= 3.1.0"])
|
72
74
|
end
|
73
75
|
else
|
74
|
-
s.add_dependency(%q<arel>, ["
|
75
|
-
s.add_dependency(%q<activesupport>, ["
|
76
|
+
s.add_dependency(%q<arel>, ["~> 2.2.1"])
|
77
|
+
s.add_dependency(%q<activesupport>, ["~> 3.1.0"])
|
76
78
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
77
79
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
78
80
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
79
81
|
s.add_dependency(%q<rcov>, [">= 0"])
|
80
|
-
s.add_dependency(%q<
|
81
|
-
s.add_dependency(%q<
|
82
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
83
|
+
s.add_dependency(%q<arel>, [">= 2.2.1"])
|
84
|
+
s.add_dependency(%q<activesupport>, [">= 3.1.0"])
|
82
85
|
end
|
83
86
|
end
|
84
87
|
|
@@ -7,6 +7,7 @@ module Arel #:nodoc:
|
|
7
7
|
# List of Arel types that should be converted to make them comparable in a case-insensitive fashion
|
8
8
|
%w(Arel_Attributes_Attribute Arel_Attributes_String String).each do |arel_type_name|
|
9
9
|
define_method "visit_#{arel_type_name}_with_case_insensitive" do |obj|
|
10
|
+
# Get original value
|
10
11
|
value = send("visit_#{arel_type_name}_without_case_insensitive", obj)
|
11
12
|
|
12
13
|
# Return either the original case-sensitive value or a converted version
|
@@ -31,8 +32,23 @@ module Arel #:nodoc:
|
|
31
32
|
|
32
33
|
# Determines whether an object should be converted to case-insensitive form or not
|
33
34
|
def self.leave_case_sensitive?(obj)
|
34
|
-
|
35
|
-
|
35
|
+
if obj.is_a?(Arel::Attributes::Attribute) and obj.relation.is_a?(Arel::Table)
|
36
|
+
# Determine the attribute's type
|
37
|
+
cn = obj.relation.engine.connection_pool.connection
|
38
|
+
column = if cn.is_a?(Hash)
|
39
|
+
# This works for FakeRecord
|
40
|
+
cn.columns[obj.relation.name][obj.name.to_s]
|
41
|
+
else
|
42
|
+
# This works for Oracle Enhanced
|
43
|
+
cn.columns(obj.relation.name).find{|col|col.name.eql?(obj.name.to_s)}
|
44
|
+
end
|
45
|
+
column_type = column ? column.type : nil
|
46
|
+
return true unless column_type == :string
|
47
|
+
end
|
48
|
+
|
49
|
+
# Last checks
|
50
|
+
obj.respond_to?(:do_not_make_case_insensitive?) or
|
51
|
+
(obj.respond_to?(:name) && obj.name.eql?('*'))
|
36
52
|
end
|
37
53
|
|
38
54
|
private
|
data/test/helper.rb
CHANGED
data/test/support/fake_record.rb
CHANGED
@@ -3,37 +3,36 @@ module FakeRecord
|
|
3
3
|
end
|
4
4
|
|
5
5
|
class Connection
|
6
|
-
attr_reader :tables, :columns_hash
|
6
|
+
attr_reader :tables, :columns_hash, :visitor
|
7
7
|
|
8
|
-
def initialize
|
8
|
+
def initialize(visitor)
|
9
9
|
@tables = %w{ users photos developers products}
|
10
10
|
@columns = {
|
11
11
|
'users' => [
|
12
|
-
Column.new('id', :
|
12
|
+
Column.new('id', :number),
|
13
13
|
Column.new('name', :string),
|
14
14
|
Column.new('bool', :boolean),
|
15
15
|
Column.new('created_at', :date)
|
16
16
|
],
|
17
|
-
'photos' => [
|
18
|
-
Column.new('id', :integer),
|
19
|
-
Column.new('user_name', :string),
|
20
|
-
Column.new('price', :decimal)
|
21
|
-
],
|
22
17
|
'products' => [
|
23
18
|
Column.new('id', :integer),
|
19
|
+
Column.new('name', :string),
|
24
20
|
Column.new('price', :decimal)
|
25
21
|
]
|
26
22
|
}
|
27
23
|
@columns_hash = {
|
28
24
|
'users' => Hash[@columns['users'].map { |x| [x.name, x] }],
|
29
|
-
'photos' => Hash[@columns['photos'].map { |x| [x.name, x] }],
|
30
25
|
'products' => Hash[@columns['products'].map { |x| [x.name, x] }]
|
31
26
|
}
|
32
27
|
@primary_keys = {
|
33
28
|
'users' => 'id',
|
34
|
-
'photos' => 'id',
|
35
29
|
'products' => 'id'
|
36
30
|
}
|
31
|
+
@visitor = visitor
|
32
|
+
end
|
33
|
+
|
34
|
+
def columns(table_name)
|
35
|
+
@columns[table_name]
|
37
36
|
end
|
38
37
|
|
39
38
|
def primary_key name
|
@@ -85,7 +84,7 @@ module FakeRecord
|
|
85
84
|
|
86
85
|
def initialize
|
87
86
|
@spec = Spec.new(:adapter => 'america')
|
88
|
-
@connection = Connection.new
|
87
|
+
@connection = Connection.new(Arel::Visitors::ToSql.new(self))
|
89
88
|
end
|
90
89
|
|
91
90
|
def with_connection
|
data/test/test_comparisons.rb
CHANGED
@@ -12,6 +12,8 @@ class TestComparisons < Test::Unit::TestCase
|
|
12
12
|
should_be_like @users.where(@users[:name].in(%w(Steve Barb))).to_sql, "SELECT FROM \"users\" WHERE UPPER(\"users\".\"name\") IN (UPPER('Steve'), UPPER('Barb'))"
|
13
13
|
should_be_like @users.where(@users[:name].not_in(%w(Steve Barb))).to_sql, "SELECT FROM \"users\" WHERE UPPER(\"users\".\"name\") NOT IN (UPPER('Steve'), UPPER('Barb'))"
|
14
14
|
should_be_like @users.where(@users[:name].matches_any(%w(Steve Barb))).to_sql, "SELECT FROM \"users\" WHERE (UPPER(\"users\".\"name\") LIKE UPPER('Steve') OR UPPER(\"users\".\"name\") LIKE UPPER('Barb'))"
|
15
|
+
should_be_like @users.where(@users[:id].eq(1)).to_sql, "SELECT FROM \"users\" WHERE \"users\".\"id\" = 1"
|
16
|
+
should_be_like @users.where(@users[:bool].eq(true)).to_sql, "SELECT FROM \"users\" WHERE \"users\".\"bool\" = 't'"
|
15
17
|
end
|
16
18
|
|
17
19
|
should "work correctly in case-sensitive mode" do
|
@@ -25,5 +27,8 @@ class TestComparisons < Test::Unit::TestCase
|
|
25
27
|
should_be_like @users.where(@users[:name].in(%w(Steve Barb))).to_sql, "SELECT FROM \"users\" WHERE \"users\".\"name\" IN ('Steve', 'Barb')"
|
26
28
|
should_be_like @users.where(@users[:name].not_in(%w(Steve Barb))).to_sql, "SELECT FROM \"users\" WHERE \"users\".\"name\" NOT IN ('Steve', 'Barb')"
|
27
29
|
should_be_like @users.where(@users[:name].matches_any(%w(Steve Barb))).to_sql, "SELECT FROM \"users\" WHERE (\"users\".\"name\" LIKE 'Steve' OR \"users\".\"name\" LIKE 'Barb')"
|
30
|
+
should_be_like @users.where(@users[:id].eq(1)).to_sql, "SELECT FROM \"users\" WHERE \"users\".\"id\" = 1"
|
31
|
+
should_be_like @users.where(@users[:id].eq(1)).to_sql, "SELECT FROM \"users\" WHERE \"users\".\"id\" = 1"
|
32
|
+
should_be_like @users.where(@users[:bool].eq(true)).to_sql, "SELECT FROM \"users\" WHERE \"users\".\"bool\" = 't'"
|
28
33
|
end
|
29
34
|
end
|
data/test/test_joins.rb
CHANGED
@@ -3,13 +3,13 @@ require "helper"
|
|
3
3
|
class TestJoins < Test::Unit::TestCase
|
4
4
|
should "work correctly in case-insensitive mode" do
|
5
5
|
Arel::CaseInsensitive.case_insensitive = true
|
6
|
-
should_be_like @users.join(@
|
6
|
+
should_be_like @users.join(@products).on(@users[:name].eq(@products[:name])).to_sql, "SELECT FROM \"users\" INNER JOIN \"products\" ON UPPER(\"users\".\"name\") = UPPER(\"products\".\"name\")"
|
7
7
|
should_be_like @users.join(@users2).on(@users[:name].eq(@users2[:name])).to_sql, "SELECT FROM \"users\" INNER JOIN \"users\" \"u2\" ON UPPER(\"users\".\"name\") = UPPER(\"u2\".\"name\")"
|
8
8
|
end
|
9
9
|
|
10
10
|
should "work correctly in case-sensitive mode" do
|
11
11
|
Arel::CaseInsensitive.case_insensitive = false
|
12
|
-
should_be_like @users.join(@
|
12
|
+
should_be_like @users.join(@products).on(@users[:name].eq(@products[:name])).to_sql, "SELECT FROM \"users\" INNER JOIN \"products\" ON \"users\".\"name\" = \"products\".\"name\""
|
13
13
|
should_be_like @users.join(@users2).on(@users[:name].eq(@users2[:name])).to_sql, "SELECT FROM \"users\" INNER JOIN \"users\" \"u2\" ON \"users\".\"name\" = \"u2\".\"name\""
|
14
14
|
end
|
15
15
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: case_insensitive_arel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
- 1
|
9
8
|
- 2
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Steve Lamotte
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-09-16 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -24,14 +24,14 @@ dependencies:
|
|
24
24
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 5
|
30
30
|
segments:
|
31
31
|
- 2
|
32
|
-
-
|
33
|
-
-
|
34
|
-
version: 2.
|
32
|
+
- 2
|
33
|
+
- 1
|
34
|
+
version: 2.2.1
|
35
35
|
requirement: *id001
|
36
36
|
type: :runtime
|
37
37
|
- !ruby/object:Gem::Dependency
|
@@ -40,14 +40,14 @@ dependencies:
|
|
40
40
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
45
|
+
hash: 3
|
46
46
|
segments:
|
47
47
|
- 3
|
48
|
+
- 1
|
48
49
|
- 0
|
49
|
-
|
50
|
-
version: 3.0.0
|
50
|
+
version: 3.1.0
|
51
51
|
requirement: *id002
|
52
52
|
type: :runtime
|
53
53
|
- !ruby/object:Gem::Dependency
|
@@ -112,36 +112,50 @@ dependencies:
|
|
112
112
|
type: :development
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
prerelease: false
|
115
|
-
name:
|
115
|
+
name: pry
|
116
116
|
version_requirements: &id007 !ruby/object:Gem::Requirement
|
117
117
|
none: false
|
118
118
|
requirements:
|
119
119
|
- - ">="
|
120
120
|
- !ruby/object:Gem::Version
|
121
|
-
hash:
|
121
|
+
hash: 3
|
122
122
|
segments:
|
123
|
-
- 2
|
124
123
|
- 0
|
125
|
-
|
126
|
-
version: 2.0.9
|
124
|
+
version: "0"
|
127
125
|
requirement: *id007
|
128
|
-
type: :
|
126
|
+
type: :development
|
129
127
|
- !ruby/object:Gem::Dependency
|
130
128
|
prerelease: false
|
131
|
-
name:
|
129
|
+
name: arel
|
132
130
|
version_requirements: &id008 !ruby/object:Gem::Requirement
|
133
131
|
none: false
|
134
132
|
requirements:
|
135
133
|
- - ">="
|
136
134
|
- !ruby/object:Gem::Version
|
137
|
-
hash:
|
135
|
+
hash: 5
|
138
136
|
segments:
|
139
137
|
- 2
|
140
|
-
-
|
141
|
-
-
|
142
|
-
version: 2.
|
138
|
+
- 2
|
139
|
+
- 1
|
140
|
+
version: 2.2.1
|
143
141
|
requirement: *id008
|
144
142
|
type: :runtime
|
143
|
+
- !ruby/object:Gem::Dependency
|
144
|
+
prerelease: false
|
145
|
+
name: activesupport
|
146
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
147
|
+
none: false
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
hash: 3
|
152
|
+
segments:
|
153
|
+
- 3
|
154
|
+
- 1
|
155
|
+
- 0
|
156
|
+
version: 3.1.0
|
157
|
+
requirement: *id009
|
158
|
+
type: :runtime
|
145
159
|
description: If you're using Oracle or another DBMS that has case-insensitive collation sequences, and you don't want to litter your database access code with case conversions, this gem is for you.
|
146
160
|
email: steve@lexor.ca
|
147
161
|
executables: []
|