imw 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +15 -0
- data/CHANGELOG +0 -0
- data/LICENSE +674 -0
- data/README.rdoc +101 -0
- data/Rakefile +20 -0
- data/VERSION +1 -0
- data/etc/imwrc.rb +76 -0
- data/lib/imw.rb +42 -0
- data/lib/imw/boot.rb +58 -0
- data/lib/imw/dataset.rb +233 -0
- data/lib/imw/dataset/datamapper.rb +66 -0
- data/lib/imw/dataset/datamapper/time_and_user_stamps.rb +37 -0
- data/lib/imw/dataset/loaddump.rb +50 -0
- data/lib/imw/dataset/old/file_collection.rb +88 -0
- data/lib/imw/dataset/old/file_collection_utils.rb +71 -0
- data/lib/imw/dataset/scaffold.rb +132 -0
- data/lib/imw/dataset/scraped_uri.rb +305 -0
- data/lib/imw/dataset/scrub/old_working_scrubber.rb +87 -0
- data/lib/imw/dataset/scrub/scrub.rb +147 -0
- data/lib/imw/dataset/scrub/scrub_simple_url.rb +38 -0
- data/lib/imw/dataset/scrub/scrub_test.rb +60 -0
- data/lib/imw/dataset/scrub/slug.rb +101 -0
- data/lib/imw/dataset/stats.rb +73 -0
- data/lib/imw/dataset/stats/counter.rb +23 -0
- data/lib/imw/dataset/task.rb +38 -0
- data/lib/imw/dataset/workflow.rb +81 -0
- data/lib/imw/files.rb +110 -0
- data/lib/imw/files/archive.rb +113 -0
- data/lib/imw/files/basicfile.rb +122 -0
- data/lib/imw/files/binary.rb +28 -0
- data/lib/imw/files/compressed_file.rb +93 -0
- data/lib/imw/files/compressed_files_and_archives.rb +348 -0
- data/lib/imw/files/compressible.rb +103 -0
- data/lib/imw/files/csv.rb +112 -0
- data/lib/imw/files/json.rb +41 -0
- data/lib/imw/files/sgml.rb +65 -0
- data/lib/imw/files/text.rb +68 -0
- data/lib/imw/files/yaml.rb +46 -0
- data/lib/imw/packagers.rb +8 -0
- data/lib/imw/packagers/archiver.rb +108 -0
- data/lib/imw/packagers/s3_mover.rb +28 -0
- data/lib/imw/parsers.rb +7 -0
- data/lib/imw/parsers/html_parser.rb +382 -0
- data/lib/imw/parsers/html_parser/matchers.rb +306 -0
- data/lib/imw/parsers/line_parser.rb +87 -0
- data/lib/imw/parsers/regexp_parser.rb +72 -0
- data/lib/imw/utils.rb +24 -0
- data/lib/imw/utils/components.rb +61 -0
- data/lib/imw/utils/config.rb +46 -0
- data/lib/imw/utils/error.rb +54 -0
- data/lib/imw/utils/extensions/array.rb +125 -0
- data/lib/imw/utils/extensions/class/attribute_accessors.rb +8 -0
- data/lib/imw/utils/extensions/core.rb +43 -0
- data/lib/imw/utils/extensions/dir.rb +24 -0
- data/lib/imw/utils/extensions/file_core.rb +64 -0
- data/lib/imw/utils/extensions/hash.rb +218 -0
- data/lib/imw/utils/extensions/hpricot.rb +48 -0
- data/lib/imw/utils/extensions/string.rb +49 -0
- data/lib/imw/utils/extensions/struct.rb +42 -0
- data/lib/imw/utils/extensions/symbol.rb +28 -0
- data/lib/imw/utils/extensions/typed_struct.rb +22 -0
- data/lib/imw/utils/extensions/uri.rb +59 -0
- data/lib/imw/utils/log.rb +67 -0
- data/lib/imw/utils/misc.rb +63 -0
- data/lib/imw/utils/paths.rb +115 -0
- data/lib/imw/utils/uri.rb +59 -0
- data/lib/imw/utils/uuid.rb +33 -0
- data/lib/imw/utils/validate.rb +38 -0
- data/lib/imw/utils/version.rb +12 -0
- data/lib/imw/utils/view.rb +113 -0
- data/lib/imw/utils/view/dump_csv.rb +112 -0
- data/lib/imw/utils/view/dump_csv_older.rb +117 -0
- data/spec/data/sample.csv +131 -0
- data/spec/data/sample.tsv +131 -0
- data/spec/data/sample.txt +131 -0
- data/spec/data/sample.xml +653 -0
- data/spec/data/sample.yaml +652 -0
- data/spec/imw/dataset/datamapper/uri_spec.rb +43 -0
- data/spec/imw/dataset/datamapper_spec_helper.rb +11 -0
- data/spec/imw/files/archive_spec.rb +118 -0
- data/spec/imw/files/basicfile_spec.rb +121 -0
- data/spec/imw/files/bz2_spec.rb +32 -0
- data/spec/imw/files/compressed_file_spec.rb +96 -0
- data/spec/imw/files/compressible_spec.rb +100 -0
- data/spec/imw/files/file_spec.rb +144 -0
- data/spec/imw/files/gz_spec.rb +32 -0
- data/spec/imw/files/rar_spec.rb +33 -0
- data/spec/imw/files/tar_spec.rb +31 -0
- data/spec/imw/files/text_spec.rb +23 -0
- data/spec/imw/files/zip_spec.rb +31 -0
- data/spec/imw/files_spec.rb +38 -0
- data/spec/imw/packagers/archiver_spec.rb +125 -0
- data/spec/imw/packagers/s3_mover_spec.rb +7 -0
- data/spec/imw/parsers/line_parser_spec.rb +96 -0
- data/spec/imw/parsers/regexp_parser_spec.rb +42 -0
- data/spec/imw/utils/extensions/file_core_spec.rb +72 -0
- data/spec/imw/utils/extensions/find_spec.rb +113 -0
- data/spec/imw/utils/paths_spec.rb +38 -0
- data/spec/imw/workflow/rip/local_spec.rb +89 -0
- data/spec/imw/workflow/rip_spec.rb +27 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/archive_contents_matcher.rb +94 -0
- data/spec/support/custom_matchers.rb +21 -0
- data/spec/support/directory_contents_matcher.rb +61 -0
- data/spec/support/extensions.rb +18 -0
- data/spec/support/file_contents_matcher.rb +50 -0
- data/spec/support/random.rb +210 -0
- data/spec/support/without_regard_to_order_matcher.rb +58 -0
- 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
|