mir_extensions 0.2.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.
- data/.bundle/config +2 -0
- data/.document +5 -0
- data/.gitignore +21 -0
- data/.rspec +1 -0
- data/Gemfile +41 -0
- data/Gemfile.lock +116 -0
- data/LICENSE +20 -0
- data/README +256 -0
- data/README.rdoc +17 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/app/controllers/application_controller.rb +9 -0
- data/app/helpers/application_helper.rb +2 -0
- data/app/models/primary.rb +11 -0
- data/app/models/secondary.rb +7 -0
- data/app/views/layouts/application.html.erb +14 -0
- data/autotest/discover.rb +2 -0
- data/config.ru +4 -0
- data/config/application.rb +47 -0
- data/config/boot.rb +13 -0
- data/config/database.yml +17 -0
- data/config/environment.rb +5 -0
- data/config/environments/development.rb +22 -0
- data/config/environments/production.rb +49 -0
- data/config/environments/test.rb +35 -0
- data/config/initializers/backtrace_silencers.rb +7 -0
- data/config/initializers/inflections.rb +10 -0
- data/config/initializers/mime_types.rb +5 -0
- data/config/initializers/secret_token.rb +7 -0
- data/config/initializers/session_store.rb +8 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +58 -0
- data/db/development.sqlite3 +1 -0
- data/db/mir_ext_development.sqlite3 +0 -0
- data/db/mir_ext_test.sqlite3 +0 -0
- data/db/schema.rb +26 -0
- data/db/seeds.rb +7 -0
- data/db/test.sqlite3 +0 -0
- data/doc/README_FOR_APP +2 -0
- data/lib/core_ext/controller_extensions.rb +37 -0
- data/lib/core_ext/core_ext.rb +344 -0
- data/lib/core_ext/helper_extensions.rb +383 -0
- data/lib/mir_extensions.rb +37 -0
- data/lib/tasks/.gitkeep +0 -0
- data/log/development.log +151 -0
- data/log/production.log +0 -0
- data/log/server.log +0 -0
- data/log/test.log +27 -0
- data/mir_extensions.gemspec +119 -0
- data/public/404.html +26 -0
- data/public/422.html +26 -0
- data/public/500.html +26 -0
- data/public/favicon.ico +0 -0
- data/public/images/rails.png +0 -0
- data/public/index.html +262 -0
- data/public/javascripts/application.js +2 -0
- data/public/javascripts/controls.js +965 -0
- data/public/javascripts/dragdrop.js +974 -0
- data/public/javascripts/effects.js +1123 -0
- data/public/javascripts/prototype.js +6001 -0
- data/public/javascripts/rails.js +175 -0
- data/public/robots.txt +5 -0
- data/public/stylesheets/.gitkeep +0 -0
- data/script/rails +6 -0
- data/spec/controllers/application_controller_spec.rb +41 -0
- data/spec/helpers/application_helper_spec.rb +40 -0
- data/spec/mir_extensions_spec.rb +269 -0
- data/spec/spec_helper.rb +27 -0
- data/vendor/plugins/.gitkeep +0 -0
- metadata +170 -0
@@ -0,0 +1,175 @@
|
|
1
|
+
(function() {
|
2
|
+
// Technique from Juriy Zaytsev
|
3
|
+
// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
|
4
|
+
function isEventSupported(eventName) {
|
5
|
+
var el = document.createElement('div');
|
6
|
+
eventName = 'on' + eventName;
|
7
|
+
var isSupported = (eventName in el);
|
8
|
+
if (!isSupported) {
|
9
|
+
el.setAttribute(eventName, 'return;');
|
10
|
+
isSupported = typeof el[eventName] == 'function';
|
11
|
+
}
|
12
|
+
el = null;
|
13
|
+
return isSupported;
|
14
|
+
}
|
15
|
+
|
16
|
+
function isForm(element) {
|
17
|
+
return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'
|
18
|
+
}
|
19
|
+
|
20
|
+
function isInput(element) {
|
21
|
+
if (Object.isElement(element)) {
|
22
|
+
var name = element.nodeName.toUpperCase()
|
23
|
+
return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'
|
24
|
+
}
|
25
|
+
else return false
|
26
|
+
}
|
27
|
+
|
28
|
+
var submitBubbles = isEventSupported('submit'),
|
29
|
+
changeBubbles = isEventSupported('change')
|
30
|
+
|
31
|
+
if (!submitBubbles || !changeBubbles) {
|
32
|
+
// augment the Event.Handler class to observe custom events when needed
|
33
|
+
Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
|
34
|
+
function(init, element, eventName, selector, callback) {
|
35
|
+
init(element, eventName, selector, callback)
|
36
|
+
// is the handler being attached to an element that doesn't support this event?
|
37
|
+
if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
|
38
|
+
(!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
|
39
|
+
// "submit" => "emulated:submit"
|
40
|
+
this.eventName = 'emulated:' + this.eventName
|
41
|
+
}
|
42
|
+
}
|
43
|
+
)
|
44
|
+
}
|
45
|
+
|
46
|
+
if (!submitBubbles) {
|
47
|
+
// discover forms on the page by observing focus events which always bubble
|
48
|
+
document.on('focusin', 'form', function(focusEvent, form) {
|
49
|
+
// special handler for the real "submit" event (one-time operation)
|
50
|
+
if (!form.retrieve('emulated:submit')) {
|
51
|
+
form.on('submit', function(submitEvent) {
|
52
|
+
var emulated = form.fire('emulated:submit', submitEvent, true)
|
53
|
+
// if custom event received preventDefault, cancel the real one too
|
54
|
+
if (emulated.returnValue === false) submitEvent.preventDefault()
|
55
|
+
})
|
56
|
+
form.store('emulated:submit', true)
|
57
|
+
}
|
58
|
+
})
|
59
|
+
}
|
60
|
+
|
61
|
+
if (!changeBubbles) {
|
62
|
+
// discover form inputs on the page
|
63
|
+
document.on('focusin', 'input, select, texarea', function(focusEvent, input) {
|
64
|
+
// special handler for real "change" events
|
65
|
+
if (!input.retrieve('emulated:change')) {
|
66
|
+
input.on('change', function(changeEvent) {
|
67
|
+
input.fire('emulated:change', changeEvent, true)
|
68
|
+
})
|
69
|
+
input.store('emulated:change', true)
|
70
|
+
}
|
71
|
+
})
|
72
|
+
}
|
73
|
+
|
74
|
+
function handleRemote(element) {
|
75
|
+
var method, url, params;
|
76
|
+
|
77
|
+
var event = element.fire("ajax:before");
|
78
|
+
if (event.stopped) return false;
|
79
|
+
|
80
|
+
if (element.tagName.toLowerCase() === 'form') {
|
81
|
+
method = element.readAttribute('method') || 'post';
|
82
|
+
url = element.readAttribute('action');
|
83
|
+
params = element.serialize();
|
84
|
+
} else {
|
85
|
+
method = element.readAttribute('data-method') || 'get';
|
86
|
+
url = element.readAttribute('href');
|
87
|
+
params = {};
|
88
|
+
}
|
89
|
+
|
90
|
+
new Ajax.Request(url, {
|
91
|
+
method: method,
|
92
|
+
parameters: params,
|
93
|
+
evalScripts: true,
|
94
|
+
|
95
|
+
onComplete: function(request) { element.fire("ajax:complete", request); },
|
96
|
+
onSuccess: function(request) { element.fire("ajax:success", request); },
|
97
|
+
onFailure: function(request) { element.fire("ajax:failure", request); }
|
98
|
+
});
|
99
|
+
|
100
|
+
element.fire("ajax:after");
|
101
|
+
}
|
102
|
+
|
103
|
+
function handleMethod(element) {
|
104
|
+
var method = element.readAttribute('data-method'),
|
105
|
+
url = element.readAttribute('href'),
|
106
|
+
csrf_param = $$('meta[name=csrf-param]')[0],
|
107
|
+
csrf_token = $$('meta[name=csrf-token]')[0];
|
108
|
+
|
109
|
+
var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
|
110
|
+
element.parentNode.insert(form);
|
111
|
+
|
112
|
+
if (method !== 'post') {
|
113
|
+
var field = new Element('input', { type: 'hidden', name: '_method', value: method });
|
114
|
+
form.insert(field);
|
115
|
+
}
|
116
|
+
|
117
|
+
if (csrf_param) {
|
118
|
+
var param = csrf_param.readAttribute('content'),
|
119
|
+
token = csrf_token.readAttribute('content'),
|
120
|
+
field = new Element('input', { type: 'hidden', name: param, value: token });
|
121
|
+
form.insert(field);
|
122
|
+
}
|
123
|
+
|
124
|
+
form.submit();
|
125
|
+
}
|
126
|
+
|
127
|
+
|
128
|
+
document.on("click", "*[data-confirm]", function(event, element) {
|
129
|
+
var message = element.readAttribute('data-confirm');
|
130
|
+
if (!confirm(message)) event.stop();
|
131
|
+
});
|
132
|
+
|
133
|
+
document.on("click", "a[data-remote]", function(event, element) {
|
134
|
+
if (event.stopped) return;
|
135
|
+
handleRemote(element);
|
136
|
+
event.stop();
|
137
|
+
});
|
138
|
+
|
139
|
+
document.on("click", "a[data-method]", function(event, element) {
|
140
|
+
if (event.stopped) return;
|
141
|
+
handleMethod(element);
|
142
|
+
event.stop();
|
143
|
+
});
|
144
|
+
|
145
|
+
document.on("submit", function(event) {
|
146
|
+
var element = event.findElement(),
|
147
|
+
message = element.readAttribute('data-confirm');
|
148
|
+
if (message && !confirm(message)) {
|
149
|
+
event.stop();
|
150
|
+
return false;
|
151
|
+
}
|
152
|
+
|
153
|
+
var inputs = element.select("input[type=submit][data-disable-with]");
|
154
|
+
inputs.each(function(input) {
|
155
|
+
input.disabled = true;
|
156
|
+
input.writeAttribute('data-original-value', input.value);
|
157
|
+
input.value = input.readAttribute('data-disable-with');
|
158
|
+
});
|
159
|
+
|
160
|
+
var element = event.findElement("form[data-remote]");
|
161
|
+
if (element) {
|
162
|
+
handleRemote(element);
|
163
|
+
event.stop();
|
164
|
+
}
|
165
|
+
});
|
166
|
+
|
167
|
+
document.on("ajax:after", "form", function(event, element) {
|
168
|
+
var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
|
169
|
+
inputs.each(function(input) {
|
170
|
+
input.value = input.readAttribute('data-original-value');
|
171
|
+
input.removeAttribute('data-original-value');
|
172
|
+
input.disabled = false;
|
173
|
+
});
|
174
|
+
});
|
175
|
+
})();
|
data/public/robots.txt
ADDED
File without changes
|
data/script/rails
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
3
|
+
|
4
|
+
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
5
|
+
require File.expand_path('../../config/boot', __FILE__)
|
6
|
+
require 'rails/commands'
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe ApplicationController do
|
4
|
+
|
5
|
+
it 'detects its IP address' do
|
6
|
+
ApplicationController.local_ip.should =~ /^192\.168\.[0-9]+\.[0-9]+$|^10\.[0-9]+\.[0-9]+\.[0-9]+$|^127.0.0.1$/
|
7
|
+
end
|
8
|
+
|
9
|
+
before :all do
|
10
|
+
@controller = ApplicationController.new
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'sanitizes the sort-by param' do
|
14
|
+
@controller.stubs(:params).returns(:by => 'SELECT * FROM accounts')
|
15
|
+
@controller.sanitize_by_param.should == 'id'
|
16
|
+
|
17
|
+
@controller.stubs(:params).returns(:by => 'name')
|
18
|
+
@controller.sanitize_by_param(['name']).should == 'name'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'sanitizes the sort-direction param' do
|
22
|
+
@controller.stubs(:params).returns(:dir => 'DELETE FROM accounts')
|
23
|
+
@controller.sanitize_dir_param.should == 'ASC'
|
24
|
+
|
25
|
+
@controller.stubs(:params).returns(:dir => 'ASC')
|
26
|
+
@controller.sanitize_dir_param.should == 'ASC'
|
27
|
+
|
28
|
+
@controller.stubs(:params).returns(:dir => 'DESC')
|
29
|
+
@controller.sanitize_dir_param.should == 'DESC'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'sanitizes params' do
|
33
|
+
@controller.sanitize_params( 2, [1, 2, 3], 1).should == 2
|
34
|
+
@controller.sanitize_params( 0, [1, 2, 3], 1).should == 1
|
35
|
+
@controller.sanitize_params( nil, [1, 2, 3], 1).should == 1
|
36
|
+
@controller.sanitize_params( 0, nil, 1).should == 1
|
37
|
+
lambda{ @controller.sanitize_params( 0, [1, 2, 3], nil) }.should raise_error(ArgumentError)
|
38
|
+
@controller.sanitize_params( nil, nil, 1).should == 1
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe ApplicationHelper do
|
4
|
+
|
5
|
+
it 'detects its action' do
|
6
|
+
_controller = Object.new
|
7
|
+
_controller.stubs(:action_name).returns('index')
|
8
|
+
controller.stubs(:controller).returns(_controller)
|
9
|
+
controller.action?('index').should be_true
|
10
|
+
controller.action?('destroy').should be_false
|
11
|
+
controller.action?(/index|show/).should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'formats arrays as HTML lines' do
|
15
|
+
controller.array_to_lines([:a, :b, :c]).should == 'a<br />b<br />c'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns a check-mark div' do
|
19
|
+
controller.checkmark.should == '<div class="checkmark"></div>'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'detects its action' do
|
23
|
+
_controller = Object.new
|
24
|
+
_controller.stubs(:controller_name).returns('home')
|
25
|
+
controller.stubs(:controller).returns(_controller)
|
26
|
+
controller.controller?('home').should be_true
|
27
|
+
controller.controller?('primary').should be_false
|
28
|
+
controller.controller?(/home|primary/).should be_true
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'returns an options string with the default select prompt' do
|
32
|
+
controller.options_for_array([['1', 'Option 1'], ['2', 'Option 2'], ['3', 'Option 3']]).should == "#{controller.select_prompt_option}<option value=\"1\" >Option 1</option><option value=\"2\" >Option 2</option><option value=\"3\" >Option 3</option>"
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns an options string with the default select prompt and a default value' do
|
36
|
+
controller.options_for_array([['1', 'Option 1'], ['2', 'Option 2'], ['3', 'Option 3']], '2').should == "#{controller.select_prompt_option}<option value=\"1\" >Option 1</option><option value=\"2\" selected=\"1\">Option 2</option><option value=\"3\" >Option 3</option>"
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "MirExtensions" do
|
4
|
+
|
5
|
+
describe 'class methods' do
|
6
|
+
|
7
|
+
describe 'state codes' do
|
8
|
+
|
9
|
+
it 'returns the state code for a given state' do
|
10
|
+
MirExtensions.state_code_for('Virginia').should == 'VA'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns the state for a given state code' do
|
14
|
+
MirExtensions.state_name_for('VA').should == 'Virginia'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'handles failures gracefully' do
|
18
|
+
MirExtensions.state_name_for('XX').should be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns the month name for a month number' do
|
24
|
+
MirExtensions.month_name_for(0).should == 'JAN'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns a canonical URL' do
|
28
|
+
MirExtensions.canonical_url('cnn.com').should == 'cnn.com/'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'normalizes slugs' do
|
32
|
+
MirExtensions.normalize_slug('!@#$%^&*()').should == ''
|
33
|
+
MirExtensions.normalize_slug('abcdefghijklmnopqrstuvwxyz').should == 'abcdefghijklmnopqrstuvwxyz'
|
34
|
+
MirExtensions.normalize_slug('ABCDEFGHIJKLMNOPQRSTUVWXYZ').should == 'abcdefghijklmnopqrstuvwxyz'
|
35
|
+
MirExtensions.normalize_slug('0123456789').should == '0123456789'
|
36
|
+
MirExtensions.normalize_slug('mir-utility').should == 'mir-utility'
|
37
|
+
MirExtensions.normalize_slug('mir--utility').should == 'mir-utility'
|
38
|
+
MirExtensions.normalize_slug('mir-utility').should == 'mir-utility'
|
39
|
+
MirExtensions.normalize_slug('mir-utility/index//').should == 'mir-utility-index'
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'string extensions' do
|
45
|
+
|
46
|
+
it 'formats phone numbers' do
|
47
|
+
'3125555252'.to_phone.should == '312-555-5252'
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'formats phone numbers, accepting options' do
|
51
|
+
'3125555252'.to_phone(:area_code => true).should == '(312) 555-5252'
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'formats phone numbers' do
|
57
|
+
''.number_to_phone('5168675309').should == '516-867-5309'
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'formats phone numbers with separate area codes' do
|
61
|
+
'5168675309'.formatted_phone.should == '(516) 867-5309'
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'handles invalid phone numbers gracefully' do
|
65
|
+
'Alphabet Soup'.formatted_phone.should == 'Alphabet Soup'
|
66
|
+
'Transylvania 6-5000'.formatted_phone.should == 'Transylvania 6-5000'
|
67
|
+
'123-45-6789'.formatted_phone.should == '123-45-6789'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'formats zip codes' do
|
71
|
+
'205000003'.formatted_zip.should == '20500-0003'
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'calculates arithmetic means' do
|
75
|
+
_a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
|
76
|
+
_a.mean.should == (_a.sum.to_f/_a.size.to_f).to_f
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'aliases count to size' do
|
80
|
+
_a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
|
81
|
+
_a.count.should == _a.size
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'converts seconds to hours:minutes:seconds' do
|
85
|
+
86400.to_hrs_mins_secs.should == '24:00:00'
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'rounds to the nearest tenth' do
|
89
|
+
Math::PI.to_nearest_tenth.should == 3.1
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'converts active records to an array of name-value pairs suitable for select tags' do
|
93
|
+
Primary.stubs(:all).returns([Primary.new(:name => 'Admin'), Primary.new(:name => 'User')])
|
94
|
+
Primary.to_option_values.should == [ ['Admin', nil], ['User', nil] ]
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'strips the values of specified attributes' do
|
98
|
+
p = Primary.new(:name => ' foo bar ')
|
99
|
+
p.strip(:name)
|
100
|
+
p.name.should == 'foo bar'
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'converts arrays to a histogram hash' do
|
104
|
+
[:r, :r, :o, :y, :g, :b, :i, :v, :v, :o].to_histogram.should == {:o=>2, :g=>1, :v=>2, :r=>2, :i=>1, :y=>1, :b=>1}
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'converts a hash to HTTP parameters' do
|
108
|
+
_return = {
|
109
|
+
:string => 1,
|
110
|
+
:array => [2, 3],
|
111
|
+
:hash => {
|
112
|
+
:a => 4,
|
113
|
+
:b => {
|
114
|
+
:c => 5
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}.to_params
|
118
|
+
|
119
|
+
_return.include?('string=1').should be_true
|
120
|
+
_return.include?('array[0]=2&array[1]=3').should be_true
|
121
|
+
_return.include?('hash[a]=4').should be_true
|
122
|
+
_return.include?('hash[b][c]=5').should be_true
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'converts a hash to SQL conditions' do
|
126
|
+
_hash = {
|
127
|
+
:first_name => 'Quentin',
|
128
|
+
:last_name => 'Tarantino'
|
129
|
+
}
|
130
|
+
_hash.to_sql.should =~ /first_name = 'Quentin'/
|
131
|
+
_hash.to_sql.should =~ /last_name = 'Tarantino'/
|
132
|
+
_hash.to_sql.should =~ / AND /
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'initializes SOAP headers' do
|
136
|
+
_control = {
|
137
|
+
:tag => '',
|
138
|
+
:value => ''
|
139
|
+
}
|
140
|
+
_header = Header.new( _control[:tag], _control[:value] )
|
141
|
+
_header.on_simple_outbound.should == _control[:value]
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'capitalizes words without omitting characters like titleize' do
|
145
|
+
'vice-president of the united states of america'.capitalize_words.should == 'Vice-President Of The United States Of America'
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'expands address abbreviations' do
|
149
|
+
_control = {
|
150
|
+
'1600 Pennsylvania Av' => '1600 Pennsylvania Avenue',
|
151
|
+
'1600 Pennsylvania Av.' => '1600 Pennsylvania Avenue',
|
152
|
+
'1600 Pennsylvania Ave' => '1600 Pennsylvania Avenue',
|
153
|
+
'1600 Pennsylvania Ave.' => '1600 Pennsylvania Avenue',
|
154
|
+
'77 Sunset Bl' => '77 Sunset Boulevard',
|
155
|
+
'77 Sunset Bl.' => '77 Sunset Boulevard',
|
156
|
+
'77 Sunset Bld' => '77 Sunset Boulevard',
|
157
|
+
'77 Sunset Bld.' => '77 Sunset Boulevard',
|
158
|
+
'77 Sunset Blv' => '77 Sunset Boulevard',
|
159
|
+
'77 Sunset Blv.' => '77 Sunset Boulevard',
|
160
|
+
'77 Sunset Blvd' => '77 Sunset Boulevard',
|
161
|
+
'77 Sunset Blvd.' => '77 Sunset Boulevard',
|
162
|
+
'10 Columbus Cr' => '10 Columbus Circle',
|
163
|
+
'10 Columbus Cr.' => '10 Columbus Circle',
|
164
|
+
'10 Lincoln Ctr Plz' => '10 Lincoln Center Plaza',
|
165
|
+
'10 Lincoln Ctr. Plz.' => '10 Lincoln Center Plaza',
|
166
|
+
'157 King Arthur Ct' => '157 King Arthur Court',
|
167
|
+
'157 King Arthur Ct.' => '157 King Arthur Court',
|
168
|
+
'157 King Arthur Crt' => '157 King Arthur Court',
|
169
|
+
'157 King Arthur Crt.' => '157 King Arthur Court',
|
170
|
+
'680 N Lake Shore Dr' => '680 North Lake Shore Drive',
|
171
|
+
'680 N. Lake Shore Dr.' => '680 North Lake Shore Drive',
|
172
|
+
'8900 Van Wyck Expy' => '8900 Van Wyck Expressway',
|
173
|
+
'8900 Van Wyck Expy.' => '8900 Van Wyck Expressway',
|
174
|
+
'8900 Van Wyck Expw' => '8900 Van Wyck Expressway',
|
175
|
+
'8900 Van Wyck Expw.' => '8900 Van Wyck Expressway',
|
176
|
+
'8900 Van Wyck Expressw' => '8900 Van Wyck Expressway',
|
177
|
+
'8900 Van Wyck Expressw.' => '8900 Van Wyck Expressway',
|
178
|
+
'837 E Magical Frwy' => '837 East Magical Freeway',
|
179
|
+
'837 E. Magical Frwy.' => '837 East Magical Freeway',
|
180
|
+
'750 W Sunrise Hwy' => '750 West Sunrise Highway',
|
181
|
+
'750 W. Sunrise Hwy.' => '750 West Sunrise Highway',
|
182
|
+
'9264 Penny Ln' => '9264 Penny Lane',
|
183
|
+
'9264 Penny Ln.' => '9264 Penny Lane',
|
184
|
+
'10099 Ridge Gate Pky Ste 200' => '10099 Ridge Gate Parkway Suite 200',
|
185
|
+
'10099 Ridge Gate Pky. Ste. 200' => '10099 Ridge Gate Parkway Suite 200',
|
186
|
+
'10099 Ridge Gate Pkw Suite 200' => '10099 Ridge Gate Parkway Suite 200',
|
187
|
+
'10099 Ridge Gate Pkw. Suite 200' => '10099 Ridge Gate Parkway Suite 200',
|
188
|
+
'10099 Ridge Gate Pkwy Suite 200' => '10099 Ridge Gate Parkway Suite 200',
|
189
|
+
'10099 Ridge Gate Pkwy. Suite 200' => '10099 Ridge Gate Parkway Suite 200',
|
190
|
+
'10099 Ridge Gate Prkwy Suite 200' => '10099 Ridge Gate Parkway Suite 200',
|
191
|
+
'10099 Ridge Gate Prkwy. Suite 200' => '10099 Ridge Gate Parkway Suite 200',
|
192
|
+
"5137 Zebulon's Pk" => "5137 Zebulon's Pike",
|
193
|
+
"5137 Zebulon's Pk." => "5137 Zebulon's Pike",
|
194
|
+
"King's Plz" => "King's Plaza",
|
195
|
+
"King's Plz." => "King's Plaza",
|
196
|
+
'4616 Melrose Pl' => '4616 Melrose Place',
|
197
|
+
'4616 Melrose Pl.' => '4616 Melrose Place',
|
198
|
+
'93812 S Hightower Rd' => '93812 South Hightower Road',
|
199
|
+
'93812 S. Hightower Rd.' => '93812 South Hightower Road',
|
200
|
+
'249 NE Rural Rt' => '249 Northeast Rural Route',
|
201
|
+
'249 N.E. Rural Rt.' => '249 Northeast Rural Route',
|
202
|
+
'249 NE Rural Rte' => '249 Northeast Rural Route',
|
203
|
+
'249 N.E. Rural Rte.' => '249 Northeast Rural Route',
|
204
|
+
'1 SW Main St' => '1 Southwest Main Street',
|
205
|
+
'1 S.W. Main St.' => '1 Southwest Main Street',
|
206
|
+
'1935 SE Trpk' => '1935 Southeast Turnpike',
|
207
|
+
'1935 S.E. Trpk.' => '1935 Southeast Turnpike',
|
208
|
+
'369 NW Army Tr' => '369 Northwest Army Trail',
|
209
|
+
'369 N.W. Army Tr.' => '369 Northwest Army Trail'
|
210
|
+
}
|
211
|
+
_control.keys.each do |_key|
|
212
|
+
_key.expand_address_abbreviations.should == _control[_key]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'converts 24-hour time' do
|
217
|
+
'18:20'.to_12_hour_time == '6:20 PM'
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'adds the HTTP-protocol prefix' do
|
221
|
+
'www.seologic.com'.add_http_prefix.should == 'http://www.seologic.com'
|
222
|
+
'ftp.seologic.com'.add_http_prefix.should == 'http://ftp.seologic.com'
|
223
|
+
'ftp://ftp.seologic.com'.add_http_prefix.should == 'ftp://ftp.seologic.com'
|
224
|
+
'http://'.add_http_prefix.should == 'http://'
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'detects HTTP URLs' do
|
228
|
+
'http://www.seologic.com/'.valid_http_url?.should be_true
|
229
|
+
'https://www.seologic.com/'.valid_http_url?.should be_true
|
230
|
+
'www.seologic.com'.valid_http_url?.should be_false
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'detects trailing slashes' do
|
234
|
+
'www.seologic.com'.has_http?.should be_false
|
235
|
+
'www.seologic.com/'.has_trailing_slash?.should be_true
|
236
|
+
'www.seologic.com/index'.has_trailing_slash?.should be_false
|
237
|
+
'www.seologic.com/users/'.has_trailing_slash?.should be_true
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'detects page URLs' do
|
241
|
+
'www.seologic.com'.is_page?.should be_false
|
242
|
+
'www.seologic.com/index'.is_page?.should be_false
|
243
|
+
'www.seologic.com/index.cgi'.is_page?.should be_false
|
244
|
+
'www.seologic.com/index.htm'.is_page?.should be_true
|
245
|
+
'www.seologic.com/index.html'.is_page?.should be_true
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'returns the host of a valid URI string' do
|
249
|
+
'www.seologic.com'.to_host.should be_nil
|
250
|
+
'www.seologic.com/webmaster-tools/link-popularity-check.php'.to_host.should be_nil
|
251
|
+
'http://www.seologic.com'.to_host.should == 'www.seologic.com'
|
252
|
+
'http://www.seologic.com/webmaster-tools/link-popularity-check.php'.to_host.should == 'www.seologic.com'
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'converts a URI string to a URI object' do
|
256
|
+
'www.seologic.com'.to_uri.is_a?(URI).should be_true
|
257
|
+
'http://www.seologic.com'.to_uri.is_a?(URI::HTTP).should be_true
|
258
|
+
'SEO Logic'.to_uri.should be_nil
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'detects a valid HTTP URL' do
|
262
|
+
'www.seologic.com'.valid_http_url?.should be_false
|
263
|
+
'http://'.valid_http_url?.should be_false
|
264
|
+
'http://www.seologic.com'.valid_http_url?.should be_true
|
265
|
+
'http://http://www.seologic.com'.valid_http_url?.should be_false
|
266
|
+
'SEO Logic'.valid_http_url?.should be_false
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|