linkage 0.0.4 → 0.0.5
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.
- data/Gemfile +3 -3
- data/Gemfile.lock +22 -23
- data/Guardfile +2 -0
- data/VERSION +1 -1
- data/lib/linkage/configuration.rb +14 -3
- data/lib/linkage/data.rb +4 -1
- data/lib/linkage/field.rb +1 -1
- data/lib/linkage/field_set.rb +14 -0
- data/lib/linkage/function.rb +2 -2
- data/lib/linkage/functions/strftime.rb +32 -0
- data/linkage.gemspec +15 -12
- data/test/integration/test_functions.rb +65 -0
- data/test/integration/test_self_linkage.rb +0 -23
- data/test/unit/functions/test_strftime.rb +56 -0
- data/test/unit/test_configuration.rb +19 -4
- data/test/unit/test_data.rb +6 -0
- data/test/unit/test_field.rb +5 -0
- data/test/unit/test_field_set.rb +15 -0
- data/test/unit/test_function.rb +8 -8
- metadata +111 -40
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,10 +2,10 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
blockenspiel (0.4.3)
|
5
|
-
coderay (0.
|
5
|
+
coderay (1.0.5)
|
6
6
|
ffi (1.0.11)
|
7
7
|
git (1.2.5)
|
8
|
-
guard (1.0.
|
8
|
+
guard (1.0.1)
|
9
9
|
ffi (>= 0.5.0)
|
10
10
|
thor (~> 0.14.6)
|
11
11
|
guard-test (0.4.3)
|
@@ -14,43 +14,42 @@ GEM
|
|
14
14
|
guard-yard (1.0.2)
|
15
15
|
guard (>= 0.2.2)
|
16
16
|
yard (>= 0.7.0)
|
17
|
-
jeweler (1.
|
17
|
+
jeweler (1.8.3)
|
18
18
|
bundler (~> 1.0)
|
19
19
|
git (>= 1.2.5)
|
20
20
|
rake
|
21
|
+
rdoc
|
22
|
+
json (1.6.6)
|
21
23
|
metaclass (0.0.1)
|
22
|
-
method_source (0.
|
23
|
-
|
24
|
-
mocha (0.10.3)
|
24
|
+
method_source (0.7.1)
|
25
|
+
mocha (0.10.5)
|
25
26
|
metaclass (~> 0.0.1)
|
26
27
|
mysql2 (0.3.11)
|
27
|
-
pry (0.9.
|
28
|
-
coderay (~> 0.
|
29
|
-
method_source (~> 0.
|
30
|
-
|
31
|
-
slop (~> 2.1.0)
|
28
|
+
pry (0.9.8.4)
|
29
|
+
coderay (~> 1.0.5)
|
30
|
+
method_source (~> 0.7.1)
|
31
|
+
slop (>= 2.4.4, < 3)
|
32
32
|
rake (0.9.2.2)
|
33
33
|
rdiscount (1.6.8)
|
34
|
-
|
35
|
-
|
36
|
-
sequel (3.
|
37
|
-
|
38
|
-
slop (2.1.0)
|
34
|
+
rdoc (3.12)
|
35
|
+
json (~> 1.4)
|
36
|
+
sequel (3.33.0)
|
37
|
+
slop (2.4.4)
|
39
38
|
sqlite3 (1.3.5)
|
40
|
-
test-unit (2.
|
39
|
+
test-unit (2.4.8)
|
41
40
|
thor (0.14.6)
|
42
|
-
versionomy (0.4.
|
43
|
-
blockenspiel (>= 0.4.
|
44
|
-
yard (0.7.
|
41
|
+
versionomy (0.4.2)
|
42
|
+
blockenspiel (>= 0.4.3)
|
43
|
+
yard (0.7.5)
|
45
44
|
|
46
45
|
PLATFORMS
|
47
46
|
ruby
|
48
47
|
|
49
48
|
DEPENDENCIES
|
50
|
-
bundler
|
49
|
+
bundler
|
51
50
|
guard-test
|
52
51
|
guard-yard
|
53
|
-
jeweler
|
52
|
+
jeweler
|
54
53
|
mocha
|
55
54
|
mysql2
|
56
55
|
pry
|
@@ -58,6 +57,6 @@ DEPENDENCIES
|
|
58
57
|
rdiscount
|
59
58
|
sequel
|
60
59
|
sqlite3
|
61
|
-
test-unit
|
60
|
+
test-unit
|
62
61
|
versionomy
|
63
62
|
yard
|
data/Guardfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.5
|
@@ -81,8 +81,8 @@ module Linkage
|
|
81
81
|
raise "Wonky filter"
|
82
82
|
end
|
83
83
|
|
84
|
-
arg1 = target.
|
85
|
-
arg2 = other.is_a?(DataWrapper) ? other.
|
84
|
+
arg1 = target.to_expr(@side)
|
85
|
+
arg2 = other.is_a?(DataWrapper) ? other.to_expr(@side) : other
|
86
86
|
@filter_expr =
|
87
87
|
case @operator
|
88
88
|
when :==
|
@@ -116,7 +116,7 @@ module Linkage
|
|
116
116
|
raise "Wonky expectation"
|
117
117
|
end
|
118
118
|
|
119
|
-
expr = target.
|
119
|
+
expr = target.to_expr(side)
|
120
120
|
aliased_expr = expr
|
121
121
|
if expr != merged_field.name
|
122
122
|
aliased_expr = expr.as(merged_field.name)
|
@@ -169,6 +169,10 @@ module Linkage
|
|
169
169
|
def data
|
170
170
|
@dataset.field_set[@name]
|
171
171
|
end
|
172
|
+
|
173
|
+
def to_expr(side = nil)
|
174
|
+
data.to_expr
|
175
|
+
end
|
172
176
|
end
|
173
177
|
|
174
178
|
class FunctionWrapper < DataWrapper
|
@@ -193,6 +197,11 @@ module Linkage
|
|
193
197
|
@data ||= @klass.new(*@args.collect { |arg| arg.kind_of?(DataWrapper) ? arg.data : arg })
|
194
198
|
end
|
195
199
|
|
200
|
+
def to_expr(side)
|
201
|
+
dataset = side == :lhs ? @dsl.lhs : @dsl.rhs
|
202
|
+
data.to_expr(dataset.dataset.adapter_scheme)
|
203
|
+
end
|
204
|
+
|
196
205
|
def name
|
197
206
|
data.name
|
198
207
|
end
|
@@ -222,6 +231,8 @@ module Linkage
|
|
222
231
|
end
|
223
232
|
|
224
233
|
class DatasetWrapper
|
234
|
+
attr_reader :dataset
|
235
|
+
|
225
236
|
def initialize(dsl, side, dataset)
|
226
237
|
@dsl = dsl
|
227
238
|
@dataset = dataset
|
data/lib/linkage/data.rb
CHANGED
@@ -28,7 +28,7 @@ module Linkage
|
|
28
28
|
raise NotImplementedError
|
29
29
|
end
|
30
30
|
|
31
|
-
def to_expr
|
31
|
+
def to_expr(adapter = nil)
|
32
32
|
raise NotImplementedError
|
33
33
|
end
|
34
34
|
|
@@ -54,6 +54,9 @@ module Linkage
|
|
54
54
|
# type
|
55
55
|
if type_1 != type_2
|
56
56
|
result_type = first_common_type(type_1, type_2)
|
57
|
+
if result_type.nil?
|
58
|
+
raise "Can't merge #{type_1} (#{name}) with #{type_2} (#{other.name})"
|
59
|
+
end
|
57
60
|
end
|
58
61
|
|
59
62
|
# text
|
data/lib/linkage/field.rb
CHANGED
data/lib/linkage/field_set.rb
CHANGED
@@ -12,5 +12,19 @@ module Linkage
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
def has_key?(key)
|
17
|
+
!fetch_key(key).nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def fetch_key(key)
|
21
|
+
string_key = key.to_s
|
22
|
+
keys.detect { |k| k.to_s.casecmp(string_key) == 0 }
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](key)
|
26
|
+
k = fetch_key(key)
|
27
|
+
k ? super(k) : nil
|
28
|
+
end
|
15
29
|
end
|
16
30
|
end
|
data/lib/linkage/function.rb
CHANGED
@@ -62,7 +62,7 @@ module Linkage
|
|
62
62
|
end
|
63
63
|
|
64
64
|
# @return [Sequel::SQL::Function]
|
65
|
-
def to_expr
|
65
|
+
def to_expr(adapter = nil)
|
66
66
|
self.class.function_name.to_sym.sql_function(*@values)
|
67
67
|
end
|
68
68
|
|
@@ -81,7 +81,7 @@ module Linkage
|
|
81
81
|
@names << arg.name
|
82
82
|
@static &&= arg.static?
|
83
83
|
type = arg.ruby_type[:type]
|
84
|
-
value = arg.
|
84
|
+
value = arg.to_expr
|
85
85
|
else
|
86
86
|
@names << arg.to_s.gsub(/\W/, "")
|
87
87
|
type = arg.class
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Linkage
|
2
|
+
module Functions
|
3
|
+
class Strftime < Function
|
4
|
+
def self.function_name
|
5
|
+
"strftime"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.parameters
|
9
|
+
[[Date, Time, DateTime], [String]]
|
10
|
+
end
|
11
|
+
|
12
|
+
def ruby_type
|
13
|
+
# TODO: string length needed
|
14
|
+
{:type => String}
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_expr(adapter = nil)
|
18
|
+
case adapter
|
19
|
+
when :mysql, :mysql2
|
20
|
+
:date_format.sql_function(*@values)
|
21
|
+
when :sqlite
|
22
|
+
:strftime.sql_function(@values[1], @values[0])
|
23
|
+
when :postgres
|
24
|
+
:to_char.sql_function(*@values)
|
25
|
+
else
|
26
|
+
:strftime.sql_function(@values[0], @values[1])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
Function.register(Strftime)
|
31
|
+
end
|
32
|
+
end
|
data/linkage.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "linkage"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.5"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jeremy Stephens"]
|
12
|
-
s.date = "2012-03-
|
12
|
+
s.date = "2012-03-30"
|
13
13
|
s.description = "Performs record linkage between one or two datasets, using Sequel on the backend"
|
14
14
|
s.email = "jeremy.f.stephens@vanderbilt.edu"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -33,6 +33,7 @@ Gem::Specification.new do |s|
|
|
33
33
|
"lib/linkage/field.rb",
|
34
34
|
"lib/linkage/field_set.rb",
|
35
35
|
"lib/linkage/function.rb",
|
36
|
+
"lib/linkage/functions/strftime.rb",
|
36
37
|
"lib/linkage/functions/trim.rb",
|
37
38
|
"lib/linkage/group.rb",
|
38
39
|
"lib/linkage/import_buffer.rb",
|
@@ -47,7 +48,9 @@ Gem::Specification.new do |s|
|
|
47
48
|
"test/integration/test_cross_linkage.rb",
|
48
49
|
"test/integration/test_dataset.rb",
|
49
50
|
"test/integration/test_dual_linkage.rb",
|
51
|
+
"test/integration/test_functions.rb",
|
50
52
|
"test/integration/test_self_linkage.rb",
|
53
|
+
"test/unit/functions/test_strftime.rb",
|
51
54
|
"test/unit/functions/test_trim.rb",
|
52
55
|
"test/unit/runner/test_single_threaded.rb",
|
53
56
|
"test/unit/test_configuration.rb",
|
@@ -66,7 +69,7 @@ Gem::Specification.new do |s|
|
|
66
69
|
s.homepage = "http://github.com/coupler/linkage"
|
67
70
|
s.licenses = ["MIT"]
|
68
71
|
s.require_paths = ["lib"]
|
69
|
-
s.rubygems_version = "1.
|
72
|
+
s.rubygems_version = "1.8.18"
|
70
73
|
s.summary = "Record linkage library"
|
71
74
|
|
72
75
|
if s.respond_to? :specification_version then
|
@@ -74,9 +77,9 @@ Gem::Specification.new do |s|
|
|
74
77
|
|
75
78
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
76
79
|
s.add_runtime_dependency(%q<sequel>, [">= 0"])
|
77
|
-
s.add_development_dependency(%q<bundler>, ["
|
78
|
-
s.add_development_dependency(%q<jeweler>, ["
|
79
|
-
s.add_development_dependency(%q<test-unit>, ["
|
80
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
81
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
82
|
+
s.add_development_dependency(%q<test-unit>, [">= 0"])
|
80
83
|
s.add_development_dependency(%q<mocha>, [">= 0"])
|
81
84
|
s.add_development_dependency(%q<sqlite3>, [">= 0"])
|
82
85
|
s.add_development_dependency(%q<yard>, [">= 0"])
|
@@ -89,9 +92,9 @@ Gem::Specification.new do |s|
|
|
89
92
|
s.add_development_dependency(%q<guard-yard>, [">= 0"])
|
90
93
|
else
|
91
94
|
s.add_dependency(%q<sequel>, [">= 0"])
|
92
|
-
s.add_dependency(%q<bundler>, ["
|
93
|
-
s.add_dependency(%q<jeweler>, ["
|
94
|
-
s.add_dependency(%q<test-unit>, ["
|
95
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
96
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
97
|
+
s.add_dependency(%q<test-unit>, [">= 0"])
|
95
98
|
s.add_dependency(%q<mocha>, [">= 0"])
|
96
99
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
97
100
|
s.add_dependency(%q<yard>, [">= 0"])
|
@@ -105,9 +108,9 @@ Gem::Specification.new do |s|
|
|
105
108
|
end
|
106
109
|
else
|
107
110
|
s.add_dependency(%q<sequel>, [">= 0"])
|
108
|
-
s.add_dependency(%q<bundler>, ["
|
109
|
-
s.add_dependency(%q<jeweler>, ["
|
110
|
-
s.add_dependency(%q<test-unit>, ["
|
111
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
112
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
113
|
+
s.add_dependency(%q<test-unit>, [">= 0"])
|
111
114
|
s.add_dependency(%q<mocha>, [">= 0"])
|
112
115
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
113
116
|
s.add_dependency(%q<yard>, [">= 0"])
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module IntegrationTests
|
4
|
+
class TestFunctions < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@tmpdir = Dir.mktmpdir('linkage')
|
7
|
+
@tmpuri = "sqlite://" + File.join(@tmpdir, "foo")
|
8
|
+
end
|
9
|
+
|
10
|
+
def database(options = {}, &block)
|
11
|
+
Sequel.connect(@tmpuri, options, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
FileUtils.remove_entry_secure(@tmpdir)
|
16
|
+
end
|
17
|
+
|
18
|
+
test "match functions" do
|
19
|
+
# insert the test data
|
20
|
+
database do |db|
|
21
|
+
db.create_table(:foo) { primary_key(:id); String(:bar) }
|
22
|
+
db[:foo].import([:id, :bar],
|
23
|
+
Array.new(100) { |i| [i, "bar%s" % (" " * (i % 10))] })
|
24
|
+
end
|
25
|
+
|
26
|
+
ds = Linkage::Dataset.new(@tmpuri, "foo", :single_threaded => true)
|
27
|
+
tmpuri = @tmpuri
|
28
|
+
conf = ds.link_with(ds) do
|
29
|
+
trim(lhs[:bar]).must == trim(rhs[:bar])
|
30
|
+
save_results_in(tmpuri)
|
31
|
+
end
|
32
|
+
assert_equal :self, conf.linkage_type
|
33
|
+
runner = Linkage::SingleThreadedRunner.new(conf)
|
34
|
+
runner.execute
|
35
|
+
|
36
|
+
database do |db|
|
37
|
+
assert_equal 1, db[:groups].count
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
test "strftime in sqlite" do
|
42
|
+
logger = Logger.new(STDERR)
|
43
|
+
database(:logger => logger) do |db|
|
44
|
+
db.create_table(:foo) { primary_key(:id); Date(:foo_date) }
|
45
|
+
db.create_table(:bar) { primary_key(:id); String(:bar_string) }
|
46
|
+
db[:foo].insert({:id => 1, :foo_date => Date.today})
|
47
|
+
db[:bar].insert({:id => 1, :bar_string => Date.today.strftime("%Y-%m-%d")})
|
48
|
+
end
|
49
|
+
|
50
|
+
ds_1 = Linkage::Dataset.new(@tmpuri, "foo", :single_threaded => true, :logger => logger)
|
51
|
+
ds_2 = Linkage::Dataset.new(@tmpuri, "bar", :single_threaded => true, :logger => logger)
|
52
|
+
tmpuri = @tmpuri
|
53
|
+
conf = ds_1.link_with(ds_2) do
|
54
|
+
strftime(lhs[:foo_date], "%Y-%m-%d").must == rhs[:bar_string]
|
55
|
+
save_results_in(tmpuri, :logger => logger)
|
56
|
+
end
|
57
|
+
runner = Linkage::SingleThreadedRunner.new(conf)
|
58
|
+
runner.execute
|
59
|
+
|
60
|
+
database do |db|
|
61
|
+
assert_equal 1, db[:groups].count
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -218,28 +218,5 @@ module IntegrationTests
|
|
218
218
|
end
|
219
219
|
end
|
220
220
|
end
|
221
|
-
|
222
|
-
test "match functions" do
|
223
|
-
# insert the test data
|
224
|
-
database do |db|
|
225
|
-
db.create_table(:foo) { primary_key(:id); String(:bar) }
|
226
|
-
db[:foo].import([:id, :bar],
|
227
|
-
Array.new(100) { |i| [i, "bar%s" % (" " * (i % 10))] })
|
228
|
-
end
|
229
|
-
|
230
|
-
ds = Linkage::Dataset.new(@tmpuri, "foo", :single_threaded => true)
|
231
|
-
tmpuri = @tmpuri
|
232
|
-
conf = ds.link_with(ds) do
|
233
|
-
trim(lhs[:bar]).must == trim(rhs[:bar])
|
234
|
-
save_results_in(tmpuri)
|
235
|
-
end
|
236
|
-
assert_equal :self, conf.linkage_type
|
237
|
-
runner = Linkage::SingleThreadedRunner.new(conf)
|
238
|
-
runner.execute
|
239
|
-
|
240
|
-
database do |db|
|
241
|
-
assert_equal 1, db[:groups].count
|
242
|
-
end
|
243
|
-
end
|
244
221
|
end
|
245
222
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class UnitTests::TestStrftime < Test::Unit::TestCase
|
4
|
+
def self.const_missing(name)
|
5
|
+
if Linkage::Functions.const_defined?(name)
|
6
|
+
Linkage::Functions.const_get(name)
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
test "subclass of Function" do
|
13
|
+
assert_equal Linkage::Function, Linkage::Functions::Strftime.superclass
|
14
|
+
end
|
15
|
+
|
16
|
+
test "ruby_type" do
|
17
|
+
expected = {:type => String}
|
18
|
+
format = "%Y-%m-%d"
|
19
|
+
assert_equal(expected, Linkage::Functions::Strftime.new(Time.now, format).ruby_type)
|
20
|
+
field = stub_field('field 1', :name => :bar, :ruby_type => {:type => Time})
|
21
|
+
assert_equal(expected, Linkage::Functions::Strftime.new(field, format).ruby_type)
|
22
|
+
func = new_function('foo', {:type => Time, :opts => {:junk => '123'}})
|
23
|
+
assert_equal(expected, Linkage::Functions::Strftime.new(func.new, format).ruby_type)
|
24
|
+
end
|
25
|
+
|
26
|
+
test "parameters" do
|
27
|
+
assert_equal [[Date, Time, DateTime], [String]], Linkage::Functions::Strftime.parameters
|
28
|
+
end
|
29
|
+
|
30
|
+
test "name" do
|
31
|
+
assert_equal "strftime", Linkage::Functions::Strftime.function_name
|
32
|
+
end
|
33
|
+
|
34
|
+
test "registers itself" do
|
35
|
+
assert_equal Linkage::Function["strftime"], Linkage::Functions::Strftime
|
36
|
+
end
|
37
|
+
|
38
|
+
test "to_expr for sqlite" do
|
39
|
+
args = [Time.now, "%Y-%m-%d"]
|
40
|
+
func = Strftime.new(*args)
|
41
|
+
assert_equal :strftime.sql_function(args[1], args[0]), func.to_expr(:sqlite)
|
42
|
+
end
|
43
|
+
|
44
|
+
test "to_expr for mysql" do
|
45
|
+
args = [Time.now, "%Y-%m-%d"]
|
46
|
+
func = Strftime.new(*args)
|
47
|
+
assert_equal :date_format.sql_function(*args), func.to_expr(:mysql)
|
48
|
+
assert_equal :date_format.sql_function(*args), func.to_expr(:mysql2)
|
49
|
+
end
|
50
|
+
|
51
|
+
test "to_expr for postgresql" do
|
52
|
+
args = [Time.now, "%Y-%m-%d"]
|
53
|
+
func = Strftime.new(*args)
|
54
|
+
assert_equal :to_char.sql_function(*args), func.to_expr(:postgres)
|
55
|
+
end
|
56
|
+
end
|
@@ -128,10 +128,10 @@ class UnitTests::TestConfiguration < Test::Unit::TestCase
|
|
128
128
|
end
|
129
129
|
|
130
130
|
test "dynamic database function" do
|
131
|
-
dataset_1 = stub('dataset')
|
131
|
+
dataset_1 = stub('dataset', :adapter_scheme => :sqlite)
|
132
132
|
field_1 = stub('field 1')
|
133
133
|
dataset_1.stubs(:field_set).returns({:foo => field_1})
|
134
|
-
dataset_2 = stub('dataset')
|
134
|
+
dataset_2 = stub('dataset', :adapter_scheme => :mysql2)
|
135
135
|
field_2 = stub('field 2', :to_expr => :foo)
|
136
136
|
dataset_2.stubs(:field_set).returns({:foo => field_2})
|
137
137
|
|
@@ -157,10 +157,10 @@ class UnitTests::TestConfiguration < Test::Unit::TestCase
|
|
157
157
|
end
|
158
158
|
|
159
159
|
test "static database function" do
|
160
|
-
dataset_1 = stub('dataset')
|
160
|
+
dataset_1 = stub('dataset', :adapter_scheme => :sqlite)
|
161
161
|
field_1 = stub('field 1', :to_expr => :foo)
|
162
162
|
dataset_1.stubs(:field_set).returns({:foo => field_1})
|
163
|
-
dataset_2 = stub('dataset')
|
163
|
+
dataset_2 = stub('dataset', :adapter_scheme => :mysql)
|
164
164
|
field_2 = stub('field 2')
|
165
165
|
dataset_2.stubs(:field_set).returns({:foo => field_2})
|
166
166
|
|
@@ -196,4 +196,19 @@ class UnitTests::TestConfiguration < Test::Unit::TestCase
|
|
196
196
|
Linkage::ResultSet.expects(:new).with(c).returns(result_set)
|
197
197
|
assert_equal result_set, c.result_set
|
198
198
|
end
|
199
|
+
|
200
|
+
test "case insensitive field names" do
|
201
|
+
field_1 = stub('field_1', :to_expr => :foo)
|
202
|
+
field_2 = stub('field_2', :to_expr => :bar)
|
203
|
+
field_set = {:foo => field_1, :bar => :field_2}
|
204
|
+
field_set.expects(:has_key?).with(:Foo).returns(true)
|
205
|
+
field_set.expects(:has_key?).with(:baR).returns(true)
|
206
|
+
dataset = stub('dataset', :field_set => field_set)
|
207
|
+
c = Linkage::Configuration.new(dataset, dataset)
|
208
|
+
assert_nothing_raised do
|
209
|
+
c.configure do
|
210
|
+
lhs[:Foo].must == rhs[:baR]
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
199
214
|
end
|
data/test/unit/test_data.rb
CHANGED
@@ -392,4 +392,10 @@ class UnitTests::TestData < Test::Unit::TestCase
|
|
392
392
|
result_data = data_2.merge(data_1, 'foo')
|
393
393
|
assert_equal :foo, result_data.name
|
394
394
|
end
|
395
|
+
|
396
|
+
test "merge a string field and a date field" do
|
397
|
+
data_1 = new_data(:foo, {:type => String})
|
398
|
+
data_2 = new_data(:foo, {:type => Date})
|
399
|
+
assert_raises { data_1.merge(data_2).ruby_type }
|
400
|
+
end
|
395
401
|
end
|
data/test/unit/test_field.rb
CHANGED
@@ -42,4 +42,9 @@ class UnitTests::TestField < Test::Unit::TestCase
|
|
42
42
|
field = Linkage::Field.new(:id, {:allow_null=>true, :default=>nil, :primary_key=>true, :db_type=>"integer", :type=>:integer, :ruby_default=>nil})
|
43
43
|
assert_equal :id, field.to_expr
|
44
44
|
end
|
45
|
+
|
46
|
+
test "to_expr ignores adapter argument" do
|
47
|
+
field = Linkage::Field.new(:id, {:allow_null=>true, :default=>nil, :primary_key=>true, :db_type=>"integer", :type=>:integer, :ruby_default=>nil})
|
48
|
+
assert_equal :id, field.to_expr(:foo)
|
49
|
+
end
|
45
50
|
end
|
data/test/unit/test_field_set.rb
CHANGED
@@ -28,4 +28,19 @@ class UnitTests::TestFieldSet < Test::Unit::TestCase
|
|
28
28
|
assert_equal field_2, fs[:first_name]
|
29
29
|
assert_equal field_3, fs[:last_name]
|
30
30
|
end
|
31
|
+
|
32
|
+
test "case-insensitive names" do
|
33
|
+
field_1 = stub('id field')
|
34
|
+
field_2 = stub('first_name field')
|
35
|
+
field_3 = stub('last_name field')
|
36
|
+
Linkage::Field.stubs(:new).with(:id, @schema[:id]).returns(field_1)
|
37
|
+
Linkage::Field.stubs(:new).with(:first_name, @schema[:first_name]).returns(field_2)
|
38
|
+
Linkage::Field.stubs(:new).with(:last_name, @schema[:last_name]).returns(field_3)
|
39
|
+
|
40
|
+
fs = Linkage::FieldSet.new(@schema)
|
41
|
+
assert_equal field_1, fs.primary_key
|
42
|
+
assert_equal field_1, fs[:Id]
|
43
|
+
assert_equal field_2, fs[:fIrst_name]
|
44
|
+
assert_equal field_3, fs[:laSt_name]
|
45
|
+
end
|
31
46
|
end
|
data/test/unit/test_function.rb
CHANGED
@@ -55,7 +55,7 @@ class UnitTests::TestFunction < Test::Unit::TestCase
|
|
55
55
|
|
56
56
|
test "function with field" do
|
57
57
|
klass = new_function('foo', {:type => String})
|
58
|
-
field = stub_field('field', :name => :bar, :ruby_type => {:type => String})
|
58
|
+
field = stub_field('field', :name => :bar, :to_expr => :bar, :ruby_type => {:type => String})
|
59
59
|
f = klass.new(field)
|
60
60
|
assert_equal :foo_bar, f.name
|
61
61
|
assert_equal :foo.sql_function(:bar), f.to_expr
|
@@ -66,7 +66,7 @@ class UnitTests::TestFunction < Test::Unit::TestCase
|
|
66
66
|
klass_1 = new_function('foo', {:type => String})
|
67
67
|
klass_2 = new_function('bar', {:type => String})
|
68
68
|
|
69
|
-
field = stub_field('field', :name => :baz, :ruby_type => {:type => String})
|
69
|
+
field = stub_field('field', :name => :baz, :to_expr => :baz, :ruby_type => {:type => String})
|
70
70
|
func_1 = klass_1.new(field)
|
71
71
|
assert_equal :foo_baz, func_1.name
|
72
72
|
assert !func_1.static?
|
@@ -100,7 +100,7 @@ class UnitTests::TestFunction < Test::Unit::TestCase
|
|
100
100
|
assert_equal :foo_123, func_1.name
|
101
101
|
assert func_1.static?
|
102
102
|
|
103
|
-
field = stub_field('field', :name => :quux, :ruby_type => {:type => String})
|
103
|
+
field = stub_field('field', :name => :quux, :to_expr => :quux, :ruby_type => {:type => String})
|
104
104
|
func_2 = klass_2.new(field)
|
105
105
|
assert_equal :bar_quux, func_2.name
|
106
106
|
assert !func_2.static?
|
@@ -113,8 +113,8 @@ class UnitTests::TestFunction < Test::Unit::TestCase
|
|
113
113
|
|
114
114
|
test "function with multiple fields" do
|
115
115
|
klass = new_function('foo', {:type => String})
|
116
|
-
field_1 = stub_field('field', :name => :bar, :ruby_type => {:type => String})
|
117
|
-
field_2 = stub_field('field', :name => :baz, :ruby_type => {:type => String})
|
116
|
+
field_1 = stub_field('field', :name => :bar, :to_expr => :bar, :ruby_type => {:type => String})
|
117
|
+
field_2 = stub_field('field', :name => :baz, :to_expr => :baz, :ruby_type => {:type => String})
|
118
118
|
func = klass.new(field_1, field_2)
|
119
119
|
assert_equal :foo_bar_baz, func.name
|
120
120
|
assert_equal :foo.sql_function(:bar, :baz), func.to_expr
|
@@ -123,7 +123,7 @@ class UnitTests::TestFunction < Test::Unit::TestCase
|
|
123
123
|
|
124
124
|
test "function with multiple mixed arguments" do
|
125
125
|
klass = new_function('foo', {:type => String})
|
126
|
-
field = stub_field('field', :name => :bar, :ruby_type => {:type => String})
|
126
|
+
field = stub_field('field', :name => :bar, :to_expr => :bar, :ruby_type => {:type => String})
|
127
127
|
f = klass.new(field, 123, 'abc')
|
128
128
|
assert_equal :foo_bar_123_abc, f.name
|
129
129
|
assert_equal :foo.sql_function(:bar, 123, 'abc'), f.to_expr
|
@@ -138,7 +138,7 @@ class UnitTests::TestFunction < Test::Unit::TestCase
|
|
138
138
|
test "valid parameters" do
|
139
139
|
func = new_function('foo', {:type => String}, [[String]])
|
140
140
|
assert_equal :foo.sql_function("foo"), func.new("foo").to_expr
|
141
|
-
field = stub_field('field', :name => :bar, :ruby_type => {:type => String})
|
141
|
+
field = stub_field('field', :name => :bar, :to_expr => :bar, :ruby_type => {:type => String})
|
142
142
|
assert_equal :foo.sql_function(:bar), func.new(field).to_expr
|
143
143
|
assert_equal :foo.sql_function(:foo.sql_function("hey")), func.new(func.new("hey")).to_expr
|
144
144
|
end
|
@@ -148,7 +148,7 @@ class UnitTests::TestFunction < Test::Unit::TestCase
|
|
148
148
|
assert_raises(TypeError) do
|
149
149
|
func.new(123)
|
150
150
|
end
|
151
|
-
field = stub_field('field', :name => :bar, :ruby_type => {:type => Integer})
|
151
|
+
field = stub_field('field', :name => :bar, :to_expr => :bar, :ruby_type => {:type => Integer})
|
152
152
|
assert_raises(TypeError) do
|
153
153
|
func.new(field)
|
154
154
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: linkage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
13
|
-
default_executable:
|
12
|
+
date: 2012-03-30 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: sequel
|
17
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>='
|
@@ -22,43 +21,63 @@ dependencies:
|
|
22
21
|
version: '0'
|
23
22
|
type: :runtime
|
24
23
|
prerelease: false
|
25
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
26
30
|
- !ruby/object:Gem::Dependency
|
27
31
|
name: bundler
|
28
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
29
33
|
none: false
|
30
34
|
requirements:
|
31
|
-
- -
|
35
|
+
- - ! '>='
|
32
36
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
37
|
+
version: '0'
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
37
46
|
- !ruby/object:Gem::Dependency
|
38
47
|
name: jeweler
|
39
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
40
49
|
none: false
|
41
50
|
requirements:
|
42
|
-
- -
|
51
|
+
- - ! '>='
|
43
52
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
53
|
+
version: '0'
|
45
54
|
type: :development
|
46
55
|
prerelease: false
|
47
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
48
62
|
- !ruby/object:Gem::Dependency
|
49
63
|
name: test-unit
|
50
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
51
65
|
none: false
|
52
66
|
requirements:
|
53
|
-
- -
|
67
|
+
- - ! '>='
|
54
68
|
- !ruby/object:Gem::Version
|
55
|
-
version:
|
69
|
+
version: '0'
|
56
70
|
type: :development
|
57
71
|
prerelease: false
|
58
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
59
78
|
- !ruby/object:Gem::Dependency
|
60
79
|
name: mocha
|
61
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
62
81
|
none: false
|
63
82
|
requirements:
|
64
83
|
- - ! '>='
|
@@ -66,10 +85,15 @@ dependencies:
|
|
66
85
|
version: '0'
|
67
86
|
type: :development
|
68
87
|
prerelease: false
|
69
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
70
94
|
- !ruby/object:Gem::Dependency
|
71
95
|
name: sqlite3
|
72
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
73
97
|
none: false
|
74
98
|
requirements:
|
75
99
|
- - ! '>='
|
@@ -77,10 +101,15 @@ dependencies:
|
|
77
101
|
version: '0'
|
78
102
|
type: :development
|
79
103
|
prerelease: false
|
80
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
81
110
|
- !ruby/object:Gem::Dependency
|
82
111
|
name: yard
|
83
|
-
requirement:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
84
113
|
none: false
|
85
114
|
requirements:
|
86
115
|
- - ! '>='
|
@@ -88,10 +117,15 @@ dependencies:
|
|
88
117
|
version: '0'
|
89
118
|
type: :development
|
90
119
|
prerelease: false
|
91
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
92
126
|
- !ruby/object:Gem::Dependency
|
93
127
|
name: rake
|
94
|
-
requirement:
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
95
129
|
none: false
|
96
130
|
requirements:
|
97
131
|
- - ! '>='
|
@@ -99,10 +133,15 @@ dependencies:
|
|
99
133
|
version: '0'
|
100
134
|
type: :development
|
101
135
|
prerelease: false
|
102
|
-
version_requirements:
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
103
142
|
- !ruby/object:Gem::Dependency
|
104
143
|
name: versionomy
|
105
|
-
requirement:
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
106
145
|
none: false
|
107
146
|
requirements:
|
108
147
|
- - ! '>='
|
@@ -110,10 +149,15 @@ dependencies:
|
|
110
149
|
version: '0'
|
111
150
|
type: :development
|
112
151
|
prerelease: false
|
113
|
-
version_requirements:
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
114
158
|
- !ruby/object:Gem::Dependency
|
115
159
|
name: mysql2
|
116
|
-
requirement:
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
117
161
|
none: false
|
118
162
|
requirements:
|
119
163
|
- - ! '>='
|
@@ -121,10 +165,15 @@ dependencies:
|
|
121
165
|
version: '0'
|
122
166
|
type: :development
|
123
167
|
prerelease: false
|
124
|
-
version_requirements:
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
125
174
|
- !ruby/object:Gem::Dependency
|
126
175
|
name: pry
|
127
|
-
requirement:
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
128
177
|
none: false
|
129
178
|
requirements:
|
130
179
|
- - ! '>='
|
@@ -132,10 +181,15 @@ dependencies:
|
|
132
181
|
version: '0'
|
133
182
|
type: :development
|
134
183
|
prerelease: false
|
135
|
-
version_requirements:
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ! '>='
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
136
190
|
- !ruby/object:Gem::Dependency
|
137
191
|
name: rdiscount
|
138
|
-
requirement:
|
192
|
+
requirement: !ruby/object:Gem::Requirement
|
139
193
|
none: false
|
140
194
|
requirements:
|
141
195
|
- - ! '>='
|
@@ -143,10 +197,15 @@ dependencies:
|
|
143
197
|
version: '0'
|
144
198
|
type: :development
|
145
199
|
prerelease: false
|
146
|
-
version_requirements:
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: '0'
|
147
206
|
- !ruby/object:Gem::Dependency
|
148
207
|
name: guard-test
|
149
|
-
requirement:
|
208
|
+
requirement: !ruby/object:Gem::Requirement
|
150
209
|
none: false
|
151
210
|
requirements:
|
152
211
|
- - ! '>='
|
@@ -154,10 +213,15 @@ dependencies:
|
|
154
213
|
version: '0'
|
155
214
|
type: :development
|
156
215
|
prerelease: false
|
157
|
-
version_requirements:
|
216
|
+
version_requirements: !ruby/object:Gem::Requirement
|
217
|
+
none: false
|
218
|
+
requirements:
|
219
|
+
- - ! '>='
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0'
|
158
222
|
- !ruby/object:Gem::Dependency
|
159
223
|
name: guard-yard
|
160
|
-
requirement:
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
161
225
|
none: false
|
162
226
|
requirements:
|
163
227
|
- - ! '>='
|
@@ -165,7 +229,12 @@ dependencies:
|
|
165
229
|
version: '0'
|
166
230
|
type: :development
|
167
231
|
prerelease: false
|
168
|
-
version_requirements:
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
none: false
|
234
|
+
requirements:
|
235
|
+
- - ! '>='
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: '0'
|
169
238
|
description: Performs record linkage between one or two datasets, using Sequel on
|
170
239
|
the backend
|
171
240
|
email: jeremy.f.stephens@vanderbilt.edu
|
@@ -191,6 +260,7 @@ files:
|
|
191
260
|
- lib/linkage/field.rb
|
192
261
|
- lib/linkage/field_set.rb
|
193
262
|
- lib/linkage/function.rb
|
263
|
+
- lib/linkage/functions/strftime.rb
|
194
264
|
- lib/linkage/functions/trim.rb
|
195
265
|
- lib/linkage/group.rb
|
196
266
|
- lib/linkage/import_buffer.rb
|
@@ -205,7 +275,9 @@ files:
|
|
205
275
|
- test/integration/test_cross_linkage.rb
|
206
276
|
- test/integration/test_dataset.rb
|
207
277
|
- test/integration/test_dual_linkage.rb
|
278
|
+
- test/integration/test_functions.rb
|
208
279
|
- test/integration/test_self_linkage.rb
|
280
|
+
- test/unit/functions/test_strftime.rb
|
209
281
|
- test/unit/functions/test_trim.rb
|
210
282
|
- test/unit/runner/test_single_threaded.rb
|
211
283
|
- test/unit/test_configuration.rb
|
@@ -220,7 +292,6 @@ files:
|
|
220
292
|
- test/unit/test_result_set.rb
|
221
293
|
- test/unit/test_runner.rb
|
222
294
|
- test/unit/test_utils.rb
|
223
|
-
has_rdoc: true
|
224
295
|
homepage: http://github.com/coupler/linkage
|
225
296
|
licenses:
|
226
297
|
- MIT
|
@@ -236,7 +307,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
236
307
|
version: '0'
|
237
308
|
segments:
|
238
309
|
- 0
|
239
|
-
hash:
|
310
|
+
hash: -1705215583013388953
|
240
311
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
241
312
|
none: false
|
242
313
|
requirements:
|
@@ -245,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
245
316
|
version: '0'
|
246
317
|
requirements: []
|
247
318
|
rubyforge_project:
|
248
|
-
rubygems_version: 1.
|
319
|
+
rubygems_version: 1.8.18
|
249
320
|
signing_key:
|
250
321
|
specification_version: 3
|
251
322
|
summary: Record linkage library
|