phonelib 0.2.4 → 0.2.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/README.rdoc +11 -6
- data/Rakefile +1 -1
- data/data/PhoneNumberMetaData.xml +39 -45
- data/data/phone_data.yml +6482 -6470
- data/lib/phonelib.rb +2 -1
- data/lib/phonelib/core.rb +30 -29
- data/lib/phonelib/phone.rb +52 -32
- data/lib/phonelib/version.rb +2 -1
- data/lib/tasks/phonelib_tasks.rake +14 -9
- data/lib/validators/phone_validator.rb +1 -1
- data/test/dummy/Rakefile +2 -1
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +16 -28
- data/test/dummy/log/test.log +1351 -4867
- data/test/phonelib_test.rb +35 -4
- metadata +122 -126
- checksums.yaml +0 -7
data/lib/phonelib.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# main module definition
|
1
2
|
module Phonelib
|
2
3
|
# load gem classes
|
3
4
|
autoload :Core, 'phonelib/core'
|
@@ -8,6 +9,6 @@ module Phonelib
|
|
8
9
|
}
|
9
10
|
end
|
10
11
|
|
11
|
-
if defined?(
|
12
|
+
if defined?(ActiveModel)
|
12
13
|
autoload :PhoneValidator, 'validators/phone_validator'
|
13
14
|
end
|
data/lib/phonelib/core.rb
CHANGED
@@ -16,25 +16,25 @@ module Phonelib
|
|
16
16
|
def default_country=(country)
|
17
17
|
@@default_country = country
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
# gem constants definition
|
21
21
|
# constants for phone types
|
22
22
|
|
23
23
|
# Validation patterns keys constants
|
24
24
|
# General pattern for country key
|
25
|
-
GENERAL = :
|
25
|
+
GENERAL = :general_desc
|
26
26
|
# Freephone line pattern key
|
27
|
-
PREMIUM_RATE = :
|
27
|
+
PREMIUM_RATE = :premium_rate
|
28
28
|
# Freephone line pattern key
|
29
|
-
TOLL_FREE = :
|
29
|
+
TOLL_FREE = :toll_free
|
30
30
|
# Shared cost pattern key. The cost of this call is shared between caller
|
31
31
|
# and recipient, and is hence typically less than PREMIUM_RATE calls
|
32
|
-
SHARED_COST = :
|
33
|
-
#
|
32
|
+
SHARED_COST = :shared_cost
|
33
|
+
# VoIP pattern key. This includes TSoIP (Telephony Service over IP)
|
34
34
|
VOIP = :voip
|
35
35
|
# A personal number is associated with a particular person, and may be
|
36
36
|
# routed to either a MOBILE or FIXED_LINE number.
|
37
|
-
PERSONAL_NUMBER = :
|
37
|
+
PERSONAL_NUMBER = :personal_number
|
38
38
|
# Pager phone number pattern key
|
39
39
|
PAGER = :pager
|
40
40
|
# Used for 'Universal Access Numbers' or 'Company Numbers'. They may be
|
@@ -44,48 +44,48 @@ module Phonelib
|
|
44
44
|
# Used for 'Voice Mail Access Numbers'.
|
45
45
|
VOICEMAIL = :voicemail
|
46
46
|
# Fixed line pattern key
|
47
|
-
FIXED_LINE = :
|
47
|
+
FIXED_LINE = :fixed_line
|
48
48
|
# Mobile phone number pattern key
|
49
49
|
MOBILE = :mobile
|
50
50
|
# In case MOBILE and FIXED patterns are the same, this type is returned
|
51
|
-
FIXED_OR_MOBILE = :
|
51
|
+
FIXED_OR_MOBILE = :fixed_or_mobile
|
52
52
|
|
53
53
|
# Internal use keys for validations
|
54
54
|
# Valid regex pattern key
|
55
|
-
VALID_PATTERN = :
|
55
|
+
VALID_PATTERN = :national_number_pattern
|
56
56
|
# Possible regex pattern key
|
57
|
-
POSSIBLE_PATTERN = :
|
57
|
+
POSSIBLE_PATTERN = :possible_number_pattern
|
58
58
|
# National prefix key
|
59
|
-
NATIONAL_PREFIX = :
|
59
|
+
NATIONAL_PREFIX = :national_prefix
|
60
60
|
# National prefix rule key
|
61
|
-
NATIONAL_PREFIX_RULE = :
|
61
|
+
NATIONAL_PREFIX_RULE = :national_prefix_formatting_rule
|
62
62
|
# Country code key
|
63
|
-
COUNTRY_CODE = :
|
63
|
+
COUNTRY_CODE = :country_code
|
64
64
|
|
65
65
|
# Default number formatting data hash
|
66
66
|
DEFAULT_NUMBER_FORMAT = {
|
67
|
-
pattern:
|
68
|
-
format:
|
67
|
+
pattern: '(\\d+)(\\d{3})(\\d{4})',
|
68
|
+
format: '$1 $2 $3'
|
69
69
|
}
|
70
70
|
|
71
71
|
# hash of all phone types with human representation
|
72
72
|
TYPES = {
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
general_desc: 'General Pattern',
|
74
|
+
premium_rate: 'Premium Rate',
|
75
|
+
toll_free: 'Toll Free',
|
76
|
+
shared_cost: 'Shared Cost',
|
77
77
|
voip: 'VoIP',
|
78
|
-
|
78
|
+
personal_number: 'Personal Number',
|
79
79
|
pager: 'Pager',
|
80
80
|
uan: 'UAN',
|
81
81
|
voicemail: 'VoiceMail',
|
82
|
-
|
82
|
+
fixed_line: 'Fixed Line',
|
83
83
|
mobile: 'Mobile',
|
84
|
-
|
84
|
+
fixed_or_mobile: 'Fixed Line or Mobile'
|
85
85
|
}
|
86
86
|
|
87
87
|
# array of types not included for validation check in cycle
|
88
|
-
NOT_FOR_CHECK = [
|
88
|
+
NOT_FOR_CHECK = [:general_desc, :fixed_line, :mobile, :fixed_or_mobile]
|
89
89
|
|
90
90
|
# method for parsing phone number.
|
91
91
|
# On first run fills @@phone_data with data present in yaml file
|
@@ -137,6 +137,7 @@ module Phonelib
|
|
137
137
|
end
|
138
138
|
|
139
139
|
private
|
140
|
+
|
140
141
|
# Load data file into memory
|
141
142
|
def load_data
|
142
143
|
require 'yaml'
|
@@ -152,18 +153,18 @@ module Phonelib
|
|
152
153
|
|
153
154
|
# Get Phone instance for provided phone with country specified
|
154
155
|
def detect_and_parse_by_country(phone, country)
|
155
|
-
detected = @@phone_data.
|
156
|
-
if
|
156
|
+
detected = @@phone_data.find { |data| data[:id] == country }
|
157
|
+
if detected
|
157
158
|
phone = convert_phone_to_e164(phone,
|
158
|
-
detected[:
|
159
|
-
detected[:
|
159
|
+
detected[:country_code],
|
160
|
+
detected[:national_prefix])
|
160
161
|
end
|
161
162
|
Phonelib::Phone.new(phone, [detected])
|
162
163
|
end
|
163
164
|
|
164
165
|
# Create phone representation in e164 format
|
165
166
|
def convert_phone_to_e164(phone, prefix, national_prefix)
|
166
|
-
return phone if phone.gsub('+','').start_with?(prefix)
|
167
|
+
return phone if phone.gsub('+', '').start_with?(prefix)
|
167
168
|
if !!national_prefix && phone.start_with?(national_prefix)
|
168
169
|
phone = phone[1..phone.length]
|
169
170
|
end
|
data/lib/phonelib/phone.rb
CHANGED
@@ -21,7 +21,7 @@ module Phonelib
|
|
21
21
|
|
22
22
|
# Returns all phone types that matched valid patterns
|
23
23
|
def types
|
24
|
-
@analyzed_data.flat_map {|iso2, data| data[:valid]}.uniq
|
24
|
+
@analyzed_data.flat_map { |iso2, data| data[:valid] }.uniq
|
25
25
|
end
|
26
26
|
|
27
27
|
# Returns first phone type that matched
|
@@ -29,21 +29,40 @@ module Phonelib
|
|
29
29
|
types.first
|
30
30
|
end
|
31
31
|
|
32
|
+
# Returns human representation of all matched phone types
|
33
|
+
def human_types
|
34
|
+
types.map { |type| Core::TYPES[type] }
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return human representation of phone type
|
38
|
+
def human_type
|
39
|
+
Core::TYPES[type]
|
40
|
+
end
|
41
|
+
|
32
42
|
# Returns all countries that matched valid patterns
|
33
43
|
def countries
|
34
|
-
@analyzed_data.map {|iso2, data| iso2}
|
44
|
+
@analyzed_data.map { |iso2, data| iso2 }
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return countries with valid patterns
|
48
|
+
def valid_countries
|
49
|
+
@valid_countries ||= countries.select do |iso2|
|
50
|
+
@analyzed_data[iso2][:valid].any?
|
51
|
+
end
|
35
52
|
end
|
36
53
|
|
37
54
|
# Returns first country that matched valid patterns
|
38
55
|
def country
|
39
|
-
@country ||=
|
40
|
-
|
56
|
+
@country ||= begin
|
57
|
+
valid_countries.find do |iso2|
|
58
|
+
@analyzed_data[iso2][:main_country_for_code] == 'true'
|
59
|
+
end || valid_countries.first
|
41
60
|
end
|
42
61
|
end
|
43
62
|
|
44
63
|
# Returns whether a current parsed phone number is valid
|
45
64
|
def valid?
|
46
|
-
@analyzed_data.select {|iso2, data| data[:valid].any? }.any?
|
65
|
+
@analyzed_data.select { |iso2, data| data[:valid].any? }.any?
|
47
66
|
end
|
48
67
|
|
49
68
|
# Returns whether a current parsed phone number is invalid
|
@@ -53,7 +72,7 @@ module Phonelib
|
|
53
72
|
|
54
73
|
# Returns whether a current parsed phone number is possible
|
55
74
|
def possible?
|
56
|
-
@analyzed_data.select {|iso2, data| data[:possible].any? }.any?
|
75
|
+
@analyzed_data.select { |iso2, data| data[:possible].any? }.any?
|
57
76
|
end
|
58
77
|
|
59
78
|
# Returns whether a current parsed phone number is impossible
|
@@ -68,11 +87,11 @@ module Phonelib
|
|
68
87
|
|
69
88
|
# add space to format groups, change first group to rule,
|
70
89
|
# change rule's constants to values
|
71
|
-
format_string = format[:format].gsub(/(\d)\$/,
|
72
|
-
gsub(/(\$NP|\$FG)/,
|
90
|
+
format_string = format[:format].gsub(/(\d)\$/, '\\1 $').gsub('$1', rule)
|
91
|
+
.gsub(/(\$NP|\$FG)/, '$NP' => prefix, '$FG' => '$1')
|
73
92
|
|
74
93
|
matches = @national_number.match(/#{format[:pattern]}/)
|
75
|
-
format_string.gsub(/\$\d/) {|el| matches[el[1].to_i] }
|
94
|
+
format_string.gsub(/\$\d/) { |el| matches[el[1].to_i] }
|
76
95
|
end
|
77
96
|
|
78
97
|
# Returns e164 formatted phone number
|
@@ -93,12 +112,14 @@ module Phonelib
|
|
93
112
|
#
|
94
113
|
# ==== Attributes
|
95
114
|
#
|
96
|
-
# * +country+ - ISO code of country (2 letters) like 'US', 'us' or :us
|
115
|
+
# * +country+ - ISO code of country (2 letters) like 'US', 'us' or :us
|
116
|
+
# for United States
|
97
117
|
#
|
98
118
|
def valid_for_country?(country)
|
99
119
|
country = country.to_s.upcase
|
100
|
-
@analyzed_data.select
|
101
|
-
|
120
|
+
@analyzed_data.select do |iso2, data|
|
121
|
+
country == iso2 && data[:valid].any?
|
122
|
+
end.any?
|
102
123
|
end
|
103
124
|
|
104
125
|
# Returns whether a current parsed phone number is invalid for specified
|
@@ -106,13 +127,15 @@ module Phonelib
|
|
106
127
|
#
|
107
128
|
# ==== Attributes
|
108
129
|
#
|
109
|
-
# * +country+ - ISO code of country (2 letters) like 'US', 'us' or :us
|
130
|
+
# * +country+ - ISO code of country (2 letters) like 'US', 'us' or :us
|
131
|
+
# for United States
|
110
132
|
#
|
111
133
|
def invalid_for_country?(country)
|
112
134
|
!valid_for_country?(country)
|
113
135
|
end
|
114
136
|
|
115
137
|
private
|
138
|
+
|
116
139
|
# Get needable data for formatting phone as national number
|
117
140
|
def get_formatting_data
|
118
141
|
format = @analyzed_data[country][:format]
|
@@ -126,13 +149,15 @@ module Phonelib
|
|
126
149
|
# Analyze current phone with provided data hash
|
127
150
|
def analyze_phone(country_data)
|
128
151
|
country_data.each do |data|
|
129
|
-
|
130
|
-
|
131
|
-
|
152
|
+
phone_code = "#{data[:country_code]}#{data[:leading_digits]}"
|
153
|
+
if @sanitized.start_with? phone_code
|
154
|
+
_possible, valid = get_patterns(data[:types][Core::GENERAL])
|
155
|
+
next unless /^#{data[:country_code]}#{valid}$/ =~ @sanitized
|
132
156
|
|
133
|
-
@national_number = @sanitized[data[:
|
157
|
+
@national_number = @sanitized[data[:country_code].length..-1]
|
134
158
|
@analyzed_data[data[:id]] = data
|
135
|
-
@analyzed_data[data[:id]][:format] =
|
159
|
+
@analyzed_data[data[:id]][:format] =
|
160
|
+
get_number_format(data[:formats])
|
136
161
|
@analyzed_data[data[:id]].merge! all_number_types(data[:types])
|
137
162
|
end
|
138
163
|
end
|
@@ -141,16 +166,11 @@ module Phonelib
|
|
141
166
|
# Returns all valid and possible phone number types for currently parsed
|
142
167
|
# phone for provided data hash.
|
143
168
|
def all_number_types(data)
|
144
|
-
response = {valid: [], possible: []}
|
145
|
-
|
146
|
-
|
147
|
-
(Core::TYPES.keys - Core::NOT_FOR_CHECK +
|
148
|
-
check_type =
|
149
|
-
when Core::FIXED_OR_MOBILE
|
150
|
-
Core::FIXED_LINE
|
151
|
-
else
|
152
|
-
type
|
153
|
-
end
|
169
|
+
response = { valid: [], possible: [] }
|
170
|
+
|
171
|
+
additional = check_same_types(data)
|
172
|
+
(Core::TYPES.keys - Core::NOT_FOR_CHECK + additional).each do |type|
|
173
|
+
check_type = (type == Core::FIXED_OR_MOBILE ? Core::FIXED_LINE : type)
|
154
174
|
possible, valid = get_patterns(data[check_type])
|
155
175
|
|
156
176
|
response[:possible] << type if number_possible?(possible)
|
@@ -164,8 +184,8 @@ module Phonelib
|
|
164
184
|
def get_number_format(format_data)
|
165
185
|
if format_data
|
166
186
|
format_data.find do |format|
|
167
|
-
(format[:
|
168
|
-
|| /^#{format[:
|
187
|
+
(format[:leading_digits].nil? \
|
188
|
+
|| /^#{format[:leading_digits]}/ =~ @national_number) \
|
169
189
|
&& /^#{format[:pattern]}$/ =~ @national_number
|
170
190
|
end
|
171
191
|
else
|
@@ -176,9 +196,9 @@ module Phonelib
|
|
176
196
|
# Checks if fixed line pattern and mobile pattern are the same
|
177
197
|
def check_same_types(data)
|
178
198
|
if data[Core::FIXED_LINE] == data[Core::MOBILE]
|
179
|
-
[
|
199
|
+
[Core::FIXED_OR_MOBILE]
|
180
200
|
else
|
181
|
-
[
|
201
|
+
[Core::FIXED_LINE, Core::MOBILE]
|
182
202
|
end
|
183
203
|
end
|
184
204
|
|
data/lib/phonelib/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
namespace :phonelib do
|
2
2
|
|
3
|
-
desc
|
3
|
+
desc 'Import and reparse original data file from Google libphonenumber'
|
4
4
|
task :import_data do
|
5
5
|
require 'net/http'
|
6
6
|
require 'yaml'
|
@@ -11,7 +11,7 @@ namespace :phonelib do
|
|
11
11
|
xml_data = Net::HTTP.get_response(URI.parse(url)).body
|
12
12
|
|
13
13
|
# save in file for debug
|
14
|
-
File.open(
|
14
|
+
File.open('data/PhoneNumberMetaData.xml', 'w+') do |f|
|
15
15
|
f.write(xml_data)
|
16
16
|
end
|
17
17
|
|
@@ -24,20 +24,20 @@ namespace :phonelib do
|
|
24
24
|
# each country
|
25
25
|
country = {}
|
26
26
|
el.attributes.each do |k, v|
|
27
|
-
country[k.to_sym] = v.to_s.tr(" \n",
|
27
|
+
country[camel2snake(k).to_sym] = v.to_s.tr(" \n", '')
|
28
28
|
end
|
29
29
|
|
30
30
|
country[:types] = {}
|
31
31
|
|
32
32
|
el.children.each do | phone_type |
|
33
33
|
if !%w(comment text).include?(phone_type.name)
|
34
|
-
phone_type_sym = phone_type.name.to_sym
|
34
|
+
phone_type_sym = camel2snake(phone_type.name).to_sym
|
35
35
|
|
36
36
|
if phone_type.name != 'availableFormats'
|
37
37
|
country[:types][phone_type_sym] = {}
|
38
38
|
phone_type.elements.each do |pattern|
|
39
|
-
country[:types][phone_type_sym][pattern.name.to_sym] =
|
40
|
-
pattern.children.first.to_s.tr(" \n",
|
39
|
+
country[:types][phone_type_sym][camel2snake(pattern.name).to_sym] =
|
40
|
+
pattern.children.first.to_s.tr(" \n", '')
|
41
41
|
end
|
42
42
|
else
|
43
43
|
country[:formats] = []
|
@@ -46,12 +46,13 @@ namespace :phonelib do
|
|
46
46
|
if !%w(comment text).include?(format.name)
|
47
47
|
current_format = {}
|
48
48
|
format.each do |f|
|
49
|
-
current_format[f[0].to_sym] = f[1]
|
49
|
+
current_format[camel2snake(f[0]).to_sym] = f[1]
|
50
50
|
end
|
51
51
|
|
52
52
|
format.children.each do |f|
|
53
53
|
if f.name != 'text'
|
54
|
-
current_format[f.name.to_sym] =
|
54
|
+
current_format[camel2snake(f.name).to_sym] =
|
55
|
+
f.children.first.to_s.gsub(/\n\s+/, '')
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
@@ -66,8 +67,12 @@ namespace :phonelib do
|
|
66
67
|
countries.push(country)
|
67
68
|
end
|
68
69
|
target = 'data/phone_data.yml'
|
69
|
-
File.open(target,
|
70
|
+
File.open(target, 'w+') do |f|
|
70
71
|
f.write(countries.to_yaml)
|
71
72
|
end
|
72
73
|
end
|
74
|
+
|
75
|
+
def camel2snake(s)
|
76
|
+
s.gsub(/[A-Z]+/) { |m| "_#{m.downcase}" }
|
77
|
+
end
|
73
78
|
end
|
data/test/dummy/Rakefile
CHANGED
Binary file
|
data/test/dummy/db/test.sqlite3
CHANGED
Binary file
|
@@ -1,31 +1,19 @@
|
|
1
1
|
Connecting to database specified by database.yml
|
2
|
-
[1m[36m (0.
|
3
|
-
[1m[35m (
|
4
|
-
[1m[36m (
|
5
|
-
[1m[35m (
|
6
|
-
|
7
|
-
[1m[
|
8
|
-
[1m[
|
9
|
-
[1m[
|
10
|
-
[1m[35m (4.1ms)[0m commit transaction
|
11
|
-
Migrating to AddPossibleNumberToPhone (20130122075331)
|
12
|
-
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
|
13
|
-
[1m[35m (0.6ms)[0m ALTER TABLE "phones" ADD "possible_number" varchar(255)
|
14
|
-
[1m[36m (0.1ms)[0m [1mINSERT INTO "schema_migrations" ("version") VALUES ('20130122075331')[0m
|
15
|
-
[1m[35m (2.7ms)[0m commit transaction
|
16
|
-
[1m[36m (0.2ms)[0m [1mSELECT "schema_migrations"."version" FROM "schema_migrations" [0m
|
2
|
+
[1m[36m (0.9ms)[0m [1mselect sqlite_version(*)[0m
|
3
|
+
[1m[35m (6.8ms)[0m CREATE TABLE "phones" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "number" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, "possible_number" varchar(255))
|
4
|
+
[1m[36m (1.4ms)[0m [1mCREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL) [0m
|
5
|
+
[1m[35m (1.6ms)[0m CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
|
6
|
+
[1m[36m (0.1ms)[0m [1mSELECT version FROM "schema_migrations"[0m
|
7
|
+
[1m[35m (3.2ms)[0m INSERT INTO "schema_migrations" (version) VALUES ('20130122075331')
|
8
|
+
[1m[36m (1.3ms)[0m [1mINSERT INTO "schema_migrations" (version) VALUES ('20130121173847')[0m
|
9
|
+
[1m[35m (0.7ms)[0m SELECT "schema_migrations"."version" FROM "schema_migrations"
|
17
10
|
Connecting to database specified by database.yml
|
18
|
-
[1m[36m (0.
|
19
|
-
[1m[35m (
|
20
|
-
[1m[36m (3.
|
21
|
-
[1m[35m (
|
22
|
-
[1m[36m (
|
23
|
-
Connecting to database specified by database.yml
|
24
|
-
[1m[36m (0.1ms)[0m [1mSELECT "schema_migrations"."version" FROM "schema_migrations" [0m
|
25
|
-
[1m[35m (0.3ms)[0m select sqlite_version(*)
|
26
|
-
[1m[36m (5.1ms)[0m [1mCREATE TABLE "phones" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "number" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, "possible_number" varchar(255)) [0m
|
27
|
-
[1m[35m (2.3ms)[0m CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL)
|
28
|
-
[1m[36m (3.4ms)[0m [1mCREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")[0m
|
11
|
+
[1m[36m (0.6ms)[0m [1mSELECT "schema_migrations"."version" FROM "schema_migrations" [0m
|
12
|
+
[1m[35m (0.1ms)[0m select sqlite_version(*)
|
13
|
+
[1m[36m (3.7ms)[0m [1mCREATE TABLE "phones" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "number" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, "possible_number" varchar(255)) [0m
|
14
|
+
[1m[35m (1.4ms)[0m CREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL)
|
15
|
+
[1m[36m (1.7ms)[0m [1mCREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")[0m
|
29
16
|
[1m[35m (0.1ms)[0m SELECT version FROM "schema_migrations"
|
30
|
-
[1m[36m (
|
31
|
-
[1m[35m (
|
17
|
+
[1m[36m (1.0ms)[0m [1mINSERT INTO "schema_migrations" (version) VALUES ('20130122075331')[0m
|
18
|
+
[1m[35m (4.9ms)[0m INSERT INTO "schema_migrations" (version) VALUES ('20130121173847')
|
19
|
+
Connecting to database specified by database.yml
|