imw 0.1.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.
Files changed (111) hide show
  1. data/.gitignore +15 -0
  2. data/CHANGELOG +0 -0
  3. data/LICENSE +674 -0
  4. data/README.rdoc +101 -0
  5. data/Rakefile +20 -0
  6. data/VERSION +1 -0
  7. data/etc/imwrc.rb +76 -0
  8. data/lib/imw.rb +42 -0
  9. data/lib/imw/boot.rb +58 -0
  10. data/lib/imw/dataset.rb +233 -0
  11. data/lib/imw/dataset/datamapper.rb +66 -0
  12. data/lib/imw/dataset/datamapper/time_and_user_stamps.rb +37 -0
  13. data/lib/imw/dataset/loaddump.rb +50 -0
  14. data/lib/imw/dataset/old/file_collection.rb +88 -0
  15. data/lib/imw/dataset/old/file_collection_utils.rb +71 -0
  16. data/lib/imw/dataset/scaffold.rb +132 -0
  17. data/lib/imw/dataset/scraped_uri.rb +305 -0
  18. data/lib/imw/dataset/scrub/old_working_scrubber.rb +87 -0
  19. data/lib/imw/dataset/scrub/scrub.rb +147 -0
  20. data/lib/imw/dataset/scrub/scrub_simple_url.rb +38 -0
  21. data/lib/imw/dataset/scrub/scrub_test.rb +60 -0
  22. data/lib/imw/dataset/scrub/slug.rb +101 -0
  23. data/lib/imw/dataset/stats.rb +73 -0
  24. data/lib/imw/dataset/stats/counter.rb +23 -0
  25. data/lib/imw/dataset/task.rb +38 -0
  26. data/lib/imw/dataset/workflow.rb +81 -0
  27. data/lib/imw/files.rb +110 -0
  28. data/lib/imw/files/archive.rb +113 -0
  29. data/lib/imw/files/basicfile.rb +122 -0
  30. data/lib/imw/files/binary.rb +28 -0
  31. data/lib/imw/files/compressed_file.rb +93 -0
  32. data/lib/imw/files/compressed_files_and_archives.rb +348 -0
  33. data/lib/imw/files/compressible.rb +103 -0
  34. data/lib/imw/files/csv.rb +112 -0
  35. data/lib/imw/files/json.rb +41 -0
  36. data/lib/imw/files/sgml.rb +65 -0
  37. data/lib/imw/files/text.rb +68 -0
  38. data/lib/imw/files/yaml.rb +46 -0
  39. data/lib/imw/packagers.rb +8 -0
  40. data/lib/imw/packagers/archiver.rb +108 -0
  41. data/lib/imw/packagers/s3_mover.rb +28 -0
  42. data/lib/imw/parsers.rb +7 -0
  43. data/lib/imw/parsers/html_parser.rb +382 -0
  44. data/lib/imw/parsers/html_parser/matchers.rb +306 -0
  45. data/lib/imw/parsers/line_parser.rb +87 -0
  46. data/lib/imw/parsers/regexp_parser.rb +72 -0
  47. data/lib/imw/utils.rb +24 -0
  48. data/lib/imw/utils/components.rb +61 -0
  49. data/lib/imw/utils/config.rb +46 -0
  50. data/lib/imw/utils/error.rb +54 -0
  51. data/lib/imw/utils/extensions/array.rb +125 -0
  52. data/lib/imw/utils/extensions/class/attribute_accessors.rb +8 -0
  53. data/lib/imw/utils/extensions/core.rb +43 -0
  54. data/lib/imw/utils/extensions/dir.rb +24 -0
  55. data/lib/imw/utils/extensions/file_core.rb +64 -0
  56. data/lib/imw/utils/extensions/hash.rb +218 -0
  57. data/lib/imw/utils/extensions/hpricot.rb +48 -0
  58. data/lib/imw/utils/extensions/string.rb +49 -0
  59. data/lib/imw/utils/extensions/struct.rb +42 -0
  60. data/lib/imw/utils/extensions/symbol.rb +28 -0
  61. data/lib/imw/utils/extensions/typed_struct.rb +22 -0
  62. data/lib/imw/utils/extensions/uri.rb +59 -0
  63. data/lib/imw/utils/log.rb +67 -0
  64. data/lib/imw/utils/misc.rb +63 -0
  65. data/lib/imw/utils/paths.rb +115 -0
  66. data/lib/imw/utils/uri.rb +59 -0
  67. data/lib/imw/utils/uuid.rb +33 -0
  68. data/lib/imw/utils/validate.rb +38 -0
  69. data/lib/imw/utils/version.rb +12 -0
  70. data/lib/imw/utils/view.rb +113 -0
  71. data/lib/imw/utils/view/dump_csv.rb +112 -0
  72. data/lib/imw/utils/view/dump_csv_older.rb +117 -0
  73. data/spec/data/sample.csv +131 -0
  74. data/spec/data/sample.tsv +131 -0
  75. data/spec/data/sample.txt +131 -0
  76. data/spec/data/sample.xml +653 -0
  77. data/spec/data/sample.yaml +652 -0
  78. data/spec/imw/dataset/datamapper/uri_spec.rb +43 -0
  79. data/spec/imw/dataset/datamapper_spec_helper.rb +11 -0
  80. data/spec/imw/files/archive_spec.rb +118 -0
  81. data/spec/imw/files/basicfile_spec.rb +121 -0
  82. data/spec/imw/files/bz2_spec.rb +32 -0
  83. data/spec/imw/files/compressed_file_spec.rb +96 -0
  84. data/spec/imw/files/compressible_spec.rb +100 -0
  85. data/spec/imw/files/file_spec.rb +144 -0
  86. data/spec/imw/files/gz_spec.rb +32 -0
  87. data/spec/imw/files/rar_spec.rb +33 -0
  88. data/spec/imw/files/tar_spec.rb +31 -0
  89. data/spec/imw/files/text_spec.rb +23 -0
  90. data/spec/imw/files/zip_spec.rb +31 -0
  91. data/spec/imw/files_spec.rb +38 -0
  92. data/spec/imw/packagers/archiver_spec.rb +125 -0
  93. data/spec/imw/packagers/s3_mover_spec.rb +7 -0
  94. data/spec/imw/parsers/line_parser_spec.rb +96 -0
  95. data/spec/imw/parsers/regexp_parser_spec.rb +42 -0
  96. data/spec/imw/utils/extensions/file_core_spec.rb +72 -0
  97. data/spec/imw/utils/extensions/find_spec.rb +113 -0
  98. data/spec/imw/utils/paths_spec.rb +38 -0
  99. data/spec/imw/workflow/rip/local_spec.rb +89 -0
  100. data/spec/imw/workflow/rip_spec.rb +27 -0
  101. data/spec/rcov.opts +1 -0
  102. data/spec/spec.opts +4 -0
  103. data/spec/spec_helper.rb +32 -0
  104. data/spec/support/archive_contents_matcher.rb +94 -0
  105. data/spec/support/custom_matchers.rb +21 -0
  106. data/spec/support/directory_contents_matcher.rb +61 -0
  107. data/spec/support/extensions.rb +18 -0
  108. data/spec/support/file_contents_matcher.rb +50 -0
  109. data/spec/support/random.rb +210 -0
  110. data/spec/support/without_regard_to_order_matcher.rb +58 -0
  111. metadata +196 -0
@@ -0,0 +1,218 @@
1
+ #
2
+ # h2. lib/imw/utils/extensions/hash.rb -- hash extensions
3
+ #
4
+ # == About
5
+ #
6
+ # Extensions to the built-in +Hash+ class.
7
+ #
8
+ # Author:: (Philip flip Kromer, Dhruv Bansal) for Infinite Monkeywrench Project (mailto:coders@infochimps.org)
9
+ # Copyright:: Copyright (c) 2008 infochimps.org
10
+ # License:: GPL 3.0
11
+ # Website:: http://infinitemonkeywrench.org/
12
+ #
13
+
14
+ require 'active_support/core_ext/hash/reverse_merge'
15
+
16
+ class Hash
17
+ # Return the elements of this hash in a pretty-printed string,
18
+ # inserting +final_string+ between the last two items.
19
+ #
20
+ # >> {:one => 1, :two => 2, :three => 3}.quote_keys_with "or"
21
+ # `one', `two', or `three'
22
+ #
23
+ def quote_keys_with final_string = nil
24
+ self.keys.quote_items_with final_string
25
+ end
26
+
27
+ # Stolen from ActiveSupport::CoreExtensions::Hash::ReverseMerge.
28
+ def reverse_merge(other_hash)
29
+ other_hash.merge(self)
30
+ end
31
+
32
+ # Stolen from ActiveSupport::CoreExtensions::Hash::ReverseMerge.
33
+ def reverse_merge!(other_hash)
34
+ replace(reverse_merge(other_hash))
35
+ end
36
+
37
+ # Create a hash from an array of keys and corresponding values.
38
+ def self.zip(keys, values, default=nil, &block)
39
+ hash = block_given? ? Hash.new(&block) : Hash.new(default)
40
+ keys.zip(values) { |k,v| hash[k]=v }
41
+ hash
42
+ end
43
+
44
+ # Turns a collection of pairs into a hash. The first of each pair
45
+ # make the keys and the second the values. Elements with length
46
+ # longer than two will lose those values.
47
+ #
48
+ # If there are multiple values of
49
+ #
50
+ def from_pairs()
51
+ hsh = { }
52
+ self.each{ |k,v| hsh[k] = v }
53
+ hsh
54
+ end
55
+
56
+ # Merges self with another hash, recursively.
57
+ #
58
+ # first = {
59
+ # :balls=> "monkey",
60
+ # :data=> {
61
+ # :name=> {:first=> "Sam", :middle=>"I", :last=>"am"}}}
62
+ # second = {
63
+ # :data=> {
64
+ # :name=> {:middle=>["you", "me", "everyone we know"], :last => "are"}},
65
+ # 1 => [1,2,5] }
66
+ #
67
+ # p first.deep_merge(second)
68
+ # # => {:data=>{:name=>{:last=>"are", :middle=>["you", "me", "everyone we know"], :first=>"Sam"}}, 1=>[1, 2, 5], :balls=>"monkey"}
69
+ # from http://snippets.dzone.com/posts/show/4706
70
+ # From: http://pastie.textmate.org/pastes/30372, Elliott Hird
71
+ def deep_merge(second)
72
+ target = dup
73
+ second.keys.each do |key|
74
+ if second[key].is_a?(Hash) && self[key].is_a?(Hash)
75
+ target[key] = target[key].deep_merge(second[key])
76
+ else
77
+ target[key] = second[key]
78
+ end
79
+ end
80
+ target
81
+ end
82
+
83
+ # Merges self in-place with another hash, recursively.
84
+ #
85
+ # first = {
86
+ # :balls=> "monkey",
87
+ # :data=> {
88
+ # :name=> {:first=> "Sam", :middle=>"I", :last=>"am"}}}
89
+ # second = {
90
+ # :data=> {
91
+ # :name=> {:middle=>["you", "me", "everyone we know"], :last => "are"}},
92
+ # 1 => [1,2,5] }
93
+ #
94
+ # p first.deep_merge(second)
95
+ # # => {:data=>{:name=>{:last=>"are", :middle=>["you", "me", "everyone we know"], :first=>"Sam"}}, 1=>[1, 2, 5], :balls=>"monkey"}
96
+ #
97
+ # From: http://www.gemtacular.com/gemdocs/cerberus-0.2.2/doc/classes/Hash.html
98
+ # File lib/cerberus/utils.rb, line 42
99
+ def deep_merge!(second)
100
+ second.keys.each do |key|
101
+ if second[key].is_a?(Hash) && self[key].is_a?(Hash)
102
+ self[key].deep_merge!(second[key])
103
+ else
104
+ self[key] = second[key]
105
+ end
106
+ end
107
+ self
108
+ end
109
+
110
+ # Merge another array with this one, accumulating values that appear in both
111
+ # into arrays.
112
+ #
113
+ # Note: array values will be flatten'ed. Sorry.
114
+ #
115
+ # first = {
116
+ # :balls=> "monkey",
117
+ # :data=> {
118
+ # :name=> {:first=> "Sam", :middle=>"I", :last=>"am"}}}
119
+ # second = {
120
+ # :data=> {
121
+ # :name=> {:middle=>["you", "me", "everyone we know"], :last => "are"}},
122
+ # 1 => [1,2,5] }
123
+ #
124
+ # p first.deep_merge(second)
125
+ # # => {:data=>{:name=>{:last=>"are", :middle=>["you", "me", "everyone we know"], :first=>"Sam"}}, 1=>[1, 2, 5], :balls=>"monkey"}
126
+ # p first.keep_merge(second)
127
+ # # => {:data=>{:name=>{:last=>["am", "are"], :middle=>["I", "you", "me", "everyone we know"], :first=>"Sam"}}, 1=>[1, 2, 5], :balls=>"monkey"}
128
+ def keep_merge(second)
129
+ target = dup
130
+ second.each do |key, val2|
131
+ if second[key].is_a?(Hash) && self[key].is_a?(Hash)
132
+ target[key] = target[key].keep_merge(val2)
133
+ else
134
+ target[key] = target.include?(key) ? [target[key], val2].flatten.uniq : val2
135
+ end
136
+ end
137
+ target
138
+ end
139
+
140
+ # This is polymorphic to Array#assoc -- that is, it allows you treat a Hash
141
+ # and an array of pairs equivalently using assoc(). We remind you that Array#assoc
142
+ #
143
+ # "Searches through an array whose elements are also arrays comparing obj
144
+ # with the first element of each contained array using obj.== . Returns the
145
+ # first contained array that matches (that is, the first associated array)
146
+ # or nil if no match is found. See also Array#rassoc."
147
+ #
148
+ # Note that this returns an /array/ of [key, val] pairs.
149
+ def assoc(key)
150
+ self.include?(key) ? [key, self[key]] : nil
151
+ end
152
+ def rassoc(key)
153
+ self.has_value?(key) ? [key, self[key]] : nil
154
+ end
155
+
156
+ # Allows loading ostruct directly from YAML
157
+ def to_openstruct
158
+ map{ |el| el.to_openstruct }
159
+ end
160
+
161
+
162
+ # Slice a hash to include only the given keys. This is useful for
163
+ # limiting an options hash to valid keys before passing to a method:
164
+ #
165
+ # def search(criteria = {})
166
+ # assert_valid_keys(:mass, :velocity, :time)
167
+ # end
168
+ #
169
+ # search(options.slice(:mass, :velocity, :time))
170
+ # Returns a new hash with only the given keys.
171
+ def slice(*keys)
172
+ allowed = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
173
+ reject { |key,| !allowed.include?(key) }
174
+ end
175
+
176
+ # Replaces the hash with only the given keys.
177
+ def slice!(*keys)
178
+ replace(slice(*keys))
179
+ end
180
+
181
+ # remove all key-value pairs where the value is nil
182
+ def compact
183
+ reject{|k,v| v.nil? }
184
+ end
185
+
186
+ # Replaces the hash with its compacted self
187
+ def compact!
188
+ replace(compact)
189
+ end
190
+
191
+ # Works like <tt>Enumerable::find</tt> but loops over the keys of
192
+ # this Hash instead of of arrays of [key,value] and, in the absence
193
+ # of a matching key, doesn't call the default argument, merely
194
+ # returns it instead.
195
+ def dispatch(default=nil, &block)
196
+ match = self.keys.find(nil,&block)
197
+ match ? self[match] : default
198
+ end
199
+
200
+
201
+ # Recurses through the pairs of this Hash collecting all String or
202
+ # Symbol "terminal" nodes.
203
+ def terminals &block
204
+ terminals = []
205
+ each_value do |value|
206
+ if value.respond_to? :terminals then
207
+ terminals += value.terminals
208
+ else
209
+ terminals << value
210
+ end
211
+ end
212
+ terminals.map! {|terminal| yield terminal } if block
213
+ terminals
214
+ end
215
+
216
+ end
217
+
218
+ # puts "#{File.basename(__FILE__)}: To each improvement there corresponds another, yes?" # at bottom
@@ -0,0 +1,48 @@
1
+ #
2
+ # h2. lib/imw/utils/extensions/hpricot.rb -- extensions to hpricot
3
+ #
4
+ # == About
5
+ #
6
+ # Some IMW extensions for Why's Hpricot library.
7
+ #
8
+ # Author:: (Philip flip Kromer, Dhruv Bansal) for Infinite Monkeywrench Project (mailto:coders@infochimps.org)
9
+ # Copyright:: Copyright (c) 2008 infochimps.org
10
+ # License:: GPL 3.0
11
+ # Website:: http://infinitemonkeywrench.org/
12
+ #
13
+ # puts "#{File.basename(__FILE__)}: Something clever" # at bottom
14
+
15
+ require 'hpricot'
16
+
17
+ module Hpricot::IMWExtensions
18
+
19
+ # Return the contents of the first element to match +path+.
20
+ def contents_of path
21
+ cnts = self.at path
22
+ cnts.inner_html if cnts
23
+ end
24
+
25
+ # Return the value of +attr+ for the first element to match +path+.
26
+ def path_attr path, attr
27
+ cnts = self.at path
28
+ cnts.attributes[attr] if cnts
29
+ end
30
+
31
+ # Return the value of the +class+ attribute of the first element to
32
+ # match +path+.
33
+ def class_of path
34
+ self.path_attr(path, 'class')
35
+ end
36
+ end
37
+
38
+ class Hpricot::Elem
39
+ include Hpricot::IMWExtensions
40
+ end
41
+
42
+ class Hpricot::Elements
43
+ include Hpricot::IMWExtensions
44
+ end
45
+
46
+ class Hpricot::Doc
47
+ include Hpricot::IMWExtensions
48
+ end
@@ -0,0 +1,49 @@
1
+ #
2
+ # h2. lib/imw/utils/extensions/string.rb -- string extensions
3
+ #
4
+ # == About
5
+ #
6
+ # Implements some useful extensions to the +String+ class.
7
+ #
8
+ # Author:: (Philip flip Kromer, Dhruv Bansal) for Infinite Monkeywrench Project (mailto:coders@infochimps.org)
9
+ # Copyright:: Copyright (c) 2008 infochimps.org
10
+ # License:: GPL 3.0
11
+ # Website:: http://infinitemonkeywrench.org/
12
+ #
13
+
14
+ class String
15
+
16
+ # Does the string end with the specified +suffix+ (stolen from
17
+ # <tt>ActiveSupport::CoreExtensions::String::StartsEndsWith</tt>)?
18
+ def ends_with?(suffix)
19
+ suffix = suffix.to_s
20
+ self[-suffix.length, suffix.length] == suffix
21
+ end
22
+
23
+ # Does the string start with the specified +prefix+ (stolen from
24
+ # <tt>ActiveSupport::CoreExtensions::String::StartsEndsWith</tt>)?
25
+ def starts_with?(prefix)
26
+ prefix = prefix.to_s
27
+ self[0, prefix.length] == prefix
28
+ end
29
+
30
+ # # Downcases a string and replaces spaces with underscores. This
31
+ # # works slightly differently than
32
+ # # <tt>ActiveSupport::CoreExtensions::String::Inflections.underscore</tt>
33
+ # # which is intended to be used for camel-cased Ruby constants.
34
+ # #
35
+ # # "A long and unwieldy phrase".underscore #=> "a_long_and_unwieldy_phrase"
36
+ # def underscore
37
+ # self.to_s.tr("-", "_").tr(" ","_").downcase
38
+ # end
39
+
40
+ # Returns the handle corresponding to this string as a symbol:
41
+ #
42
+ # "A possible title of a dataset".handle #=> :a_possible_title_of_a_dataset
43
+ def to_handle
44
+ self.downcase.underscore.to_sym
45
+ end
46
+
47
+ end
48
+
49
+ # puts "#{File.basename(__FILE__)}: You tie a long string to your Monkeywrench, place it on the ground, and hide around the corner with the string in your hand, waiting for passersby to try and make a grab for it." # at bottom
@@ -0,0 +1,42 @@
1
+ Struct.class_eval do
2
+ def slice *attrs
3
+ hsh = {}
4
+ attrs.each{|attr| hsh[attr] = self.send(attr) }
5
+ hsh
6
+ end
7
+
8
+ def to_hash
9
+ slice(*self.class.members)
10
+ end
11
+ def self.from_hash(hsh)
12
+ self.new *hsh.values_at(*self.members.map(&:to_sym))
13
+ end
14
+
15
+
16
+ #
17
+ # values_at like a hash
18
+ #
19
+ def values_of *attrs
20
+ slice(*attrs).values_at(*attrs)
21
+ end
22
+ def each_pair *args, &block
23
+ self.to_hash.each_pair(*args, &block)
24
+ end
25
+
26
+ def merge *args
27
+ self.dup.merge! *args
28
+ end
29
+ def merge! hashlike, &block
30
+ raise "can't handle block arg yet" if block
31
+ hashlike.each_pair{|k,v| self[k] = v }
32
+ self
33
+ end
34
+ alias_method :update, :merge!
35
+ def indifferent_merge *args, &block
36
+ self.dup.indifferent_merge! *args
37
+ end
38
+ def indifferent_merge! hashlike, &block
39
+ merge! hashlike.reject{|k,v| ! self.members.include?(k.to_s) }
40
+ end
41
+
42
+ end
@@ -0,0 +1,28 @@
1
+ #
2
+ # h2. lib/imw/utils/extensions/symbol.rb -- extensions to symbol class
3
+ #
4
+ # == About
5
+ #
6
+ # Author:: (Philip flip Kromer, Dhruv Bansal) for Infinite Monkeywrench Project (mailto:coders@infochimps.org)
7
+ # Copyright:: Copyright (c) 2008 infochimps.org
8
+ # License:: GPL 3.0
9
+ # Website:: http://infinitemonkeywrench.org/
10
+ #
11
+
12
+ class Symbol
13
+
14
+ # Turn the symbol into a simple proc (stolen from
15
+ # <tt>ActiveSupport::CoreExtensions::Symbol</tt>).
16
+ def to_proc
17
+ Proc.new { |*args| args.shift.__send__(self, *args) }
18
+ end
19
+
20
+ # Returns the symbol itself (for compatibility with
21
+ # <tt>String.uniqnae</tt> and so on.
22
+ def handle
23
+ self
24
+ end
25
+
26
+ end
27
+
28
+ # puts "#{File.basename(__FILE__)}: You whisper a word of power and smile as the the Ruby Palace thunders with the sound of falling blocks." # at bottom
@@ -0,0 +1,22 @@
1
+ #
2
+ # A struct
3
+ # but has an idea of what type attributes should be
4
+ #
5
+ #
6
+ class TypedStruct < Struct
7
+ def self.new attrs, convs
8
+ struct = super *attrs
9
+ struct_attr_convs = Hash.zip(attrs, convs).reject{|a,t| t.nil? }
10
+ struct.class_eval do
11
+ cattr_accessor :attr_convs
12
+ self.attr_convs = struct_attr_convs
13
+ def remap!
14
+ attr_convs.each do |attr, conv|
15
+ curr = self.send(attr)
16
+ self.send("#{attr}=", curr.send(conv)) if curr.respond_to?(conv)
17
+ end
18
+ end
19
+ end # class_eval
20
+ struct
21
+ end
22
+ end
@@ -0,0 +1,59 @@
1
+ #
2
+ # h2. lib/imw/utils/extensions/uri.rb -- extensions to uri module
3
+ #
4
+ # == About
5
+ #
6
+ # Some useful extensions to the +URI+ module.
7
+ #
8
+ # Author:: (Philip flip Kromer, Dhruv Bansal) for Infinite Monkeywrench Project (mailto:coders@infochimps.org)
9
+ # Copyright:: Copyright (c) 2008 infochimps.org
10
+ # License:: GPL 3.0
11
+ # Website:: http://infinitemonkeywrench.org/
12
+ #
13
+
14
+ require 'uri'
15
+
16
+ module URI
17
+
18
+ # List of prefixes ignored when returning domains (or reversed
19
+ # domains).
20
+ IGNORED_PREFIXES = ['www']
21
+
22
+ # Returns the domain of the given URI, first scrubbing it of any
23
+ # prefixes we can ignore.
24
+ def self.domain(uri)
25
+ uriobj = self.parse(uri)
26
+ if uriobj.host then
27
+ host = uriobj.host
28
+ elsif uriobj.path then
29
+ host = uriobj.path.split('/')[0]
30
+ else
31
+ raise ArgumentError, "Invalid URI: #{uri}"
32
+ end
33
+ # remove any ignored prefixes from the hostname (i.e. - 'www')
34
+ parts = host.split('.')
35
+ parts = (IGNORED_PREFIXES.member?(parts[0]) ? parts[1...parts.size] : parts)
36
+ host = parts.join('.')
37
+ host
38
+ end
39
+
40
+ # Returns the reversed domain of the given URI, first scrubbing it of
41
+ # any prefixes we can ignore. Will not reverse numeric addresses of
42
+ # the form 127.0.0.1
43
+ def self.reverse_domain(uri)
44
+ begin
45
+ d = self.domain(uri)
46
+ # check for numeric ip
47
+ # in a TERRIBLE way that needs to be fixed!`
48
+ if d=~/^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$/ then
49
+ return d
50
+ else
51
+ return d.split('.').reverse.join('.')
52
+ end
53
+ rescue URI::InvalidURIError,ArgumentError
54
+ raise $!
55
+ end
56
+ end
57
+ end
58
+
59
+ # puts "#{File.basename(__FILE__)}: In the end, it's either you or I." # at bottom