formattedstring 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +16 -0
- data/README +57 -0
- data/Rakefile +79 -0
- data/doc/classes/Enumerable.html +146 -0
- data/doc/classes/Enumerable.src/M000025.html +21 -0
- data/doc/classes/Enumerable.src/M000026.html +34 -0
- data/doc/classes/FormattedString/Formats/Xml.html +144 -0
- data/doc/classes/FormattedString/Formats/Xml.src/M000004.html +49 -0
- data/doc/classes/FormattedString/Formats.html +111 -0
- data/doc/classes/FormattedString.html +111 -0
- data/doc/classes/Inflector/Inflections.html +321 -0
- data/doc/classes/Inflector/Inflections.src/M000019.html +18 -0
- data/doc/classes/Inflector/Inflections.src/M000020.html +18 -0
- data/doc/classes/Inflector/Inflections.src/M000021.html +18 -0
- data/doc/classes/Inflector/Inflections.src/M000022.html +26 -0
- data/doc/classes/Inflector/Inflections.src/M000023.html +18 -0
- data/doc/classes/Inflector/Inflections.src/M000024.html +23 -0
- data/doc/classes/Inflector.html +516 -0
- data/doc/classes/Inflector.src/M000005.html +22 -0
- data/doc/classes/Inflector.src/M000006.html +25 -0
- data/doc/classes/Inflector.src/M000007.html +25 -0
- data/doc/classes/Inflector.src/M000008.html +22 -0
- data/doc/classes/Inflector.src/M000009.html +18 -0
- data/doc/classes/Inflector.src/M000010.html +22 -0
- data/doc/classes/Inflector.src/M000011.html +18 -0
- data/doc/classes/Inflector.src/M000012.html +18 -0
- data/doc/classes/Inflector.src/M000013.html +18 -0
- data/doc/classes/Inflector.src/M000014.html +18 -0
- data/doc/classes/Inflector.src/M000015.html +19 -0
- data/doc/classes/Inflector.src/M000016.html +18 -0
- data/doc/classes/Inflector.src/M000017.html +22 -0
- data/doc/classes/Inflector.src/M000018.html +27 -0
- data/doc/classes/String.html +191 -0
- data/doc/classes/String.src/M000001.html +18 -0
- data/doc/classes/String.src/M000002.html +20 -0
- data/doc/classes/String.src/M000003.html +19 -0
- data/doc/created.rid +1 -0
- data/doc/files/LICENSE.html +129 -0
- data/doc/files/README.html +196 -0
- data/doc/files/lib/formatted_string/formats/xml_rb.html +119 -0
- data/doc/files/lib/formatted_string_rb.html +108 -0
- data/doc/files/lib/inflections_rb.html +101 -0
- data/doc/files/lib/inflector_rb.html +108 -0
- data/doc/fr_class_index.html +33 -0
- data/doc/fr_file_index.html +32 -0
- data/doc/fr_method_index.html +52 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/formatted_string/formats/xml.rb +163 -0
- data/lib/formatted_string.rb +34 -0
- data/lib/inflections.rb +53 -0
- data/lib/inflector.rb +282 -0
- metadata +120 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
3
|
+
<!DOCTYPE html
|
4
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
5
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
6
|
+
|
7
|
+
<!--
|
8
|
+
|
9
|
+
Methods
|
10
|
+
|
11
|
+
-->
|
12
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
13
|
+
<head>
|
14
|
+
<title>Methods</title>
|
15
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
16
|
+
<link rel="stylesheet" href="rdoc-style.css" type="text/css" />
|
17
|
+
<base target="docwin" />
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="index">
|
21
|
+
<h1 class="section-bar">Methods</h1>
|
22
|
+
<div id="index-entries">
|
23
|
+
<a href="classes/Inflector.html#M000008">camelize (Inflector)</a><br />
|
24
|
+
<a href="classes/Inflector.html#M000015">classify (Inflector)</a><br />
|
25
|
+
<a href="classes/Inflector/Inflections.html#M000024">clear (Inflector::Inflections)</a><br />
|
26
|
+
<a href="classes/Inflector.html#M000017">constantize (Inflector)</a><br />
|
27
|
+
<a href="classes/Enumerable.html#M000026">crawl (Enumerable)</a><br />
|
28
|
+
<a href="classes/Inflector.html#M000011">dasherize (Inflector)</a><br />
|
29
|
+
<a href="classes/Inflector.html#M000013">demodulize (Inflector)</a><br />
|
30
|
+
<a href="classes/Inflector.html#M000016">foreign_key (Inflector)</a><br />
|
31
|
+
<a href="classes/String.html#M000001">format (String)</a><br />
|
32
|
+
<a href="classes/String.html#M000002">format= (String)</a><br />
|
33
|
+
<a href="classes/String.html#M000003">formatted (String)</a><br />
|
34
|
+
<a href="classes/Enumerable.html#M000025">group_by (Enumerable)</a><br />
|
35
|
+
<a href="classes/Inflector.html#M000012">humanize (Inflector)</a><br />
|
36
|
+
<a href="classes/Inflector.html#M000005">inflections (Inflector)</a><br />
|
37
|
+
<a href="classes/Inflector/Inflections.html#M000022">irregular (Inflector::Inflections)</a><br />
|
38
|
+
<a href="classes/Inflector/Inflections.html#M000019">new (Inflector::Inflections)</a><br />
|
39
|
+
<a href="classes/Inflector.html#M000018">ordinalize (Inflector)</a><br />
|
40
|
+
<a href="classes/Inflector/Inflections.html#M000020">plural (Inflector::Inflections)</a><br />
|
41
|
+
<a href="classes/Inflector.html#M000006">pluralize (Inflector)</a><br />
|
42
|
+
<a href="classes/Inflector/Inflections.html#M000021">singular (Inflector::Inflections)</a><br />
|
43
|
+
<a href="classes/Inflector.html#M000007">singularize (Inflector)</a><br />
|
44
|
+
<a href="classes/Inflector.html#M000014">tableize (Inflector)</a><br />
|
45
|
+
<a href="classes/Inflector.html#M000009">titleize (Inflector)</a><br />
|
46
|
+
<a href="classes/FormattedString/Formats/Xml.html#M000004">to_hash (FormattedString::Formats::Xml)</a><br />
|
47
|
+
<a href="classes/Inflector/Inflections.html#M000023">uncountable (Inflector::Inflections)</a><br />
|
48
|
+
<a href="classes/Inflector.html#M000010">underscore (Inflector)</a><br />
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
</body>
|
52
|
+
</html>
|
data/doc/index.html
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
5
|
+
|
6
|
+
<!--
|
7
|
+
|
8
|
+
FormattedString
|
9
|
+
|
10
|
+
-->
|
11
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
12
|
+
<head>
|
13
|
+
<title>FormattedString</title>
|
14
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
15
|
+
</head>
|
16
|
+
<frameset rows="20%, 80%">
|
17
|
+
<frameset cols="25%,35%,45%">
|
18
|
+
<frame src="fr_file_index.html" title="Files" name="Files" />
|
19
|
+
<frame src="fr_class_index.html" name="Classes" />
|
20
|
+
<frame src="fr_method_index.html" name="Methods" />
|
21
|
+
</frameset>
|
22
|
+
<frame src="files/README.html" name="docwin" />
|
23
|
+
</frameset>
|
24
|
+
</html>
|
data/doc/rdoc-style.css
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
|
2
|
+
body {
|
3
|
+
font-family: Verdana,Arial,Helvetica,sans-serif;
|
4
|
+
font-size: 90%;
|
5
|
+
margin: 0;
|
6
|
+
margin-left: 40px;
|
7
|
+
padding: 0;
|
8
|
+
background: white;
|
9
|
+
}
|
10
|
+
|
11
|
+
h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
|
12
|
+
h1 { font-size: 150%; }
|
13
|
+
h2,h3,h4 { margin-top: 1em; }
|
14
|
+
|
15
|
+
a { background: #eef; color: #039; text-decoration: none; }
|
16
|
+
a:hover { background: #039; color: #eef; }
|
17
|
+
|
18
|
+
/* Override the base stylesheet's Anchor inside a table cell */
|
19
|
+
td > a {
|
20
|
+
background: transparent;
|
21
|
+
color: #039;
|
22
|
+
text-decoration: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* and inside a section title */
|
26
|
+
.section-title > a {
|
27
|
+
background: transparent;
|
28
|
+
color: #eee;
|
29
|
+
text-decoration: none;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* === Structural elements =================================== */
|
33
|
+
|
34
|
+
div#index {
|
35
|
+
margin: 0;
|
36
|
+
margin-left: -40px;
|
37
|
+
padding: 0;
|
38
|
+
font-size: 90%;
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
div#index a {
|
43
|
+
margin-left: 0.7em;
|
44
|
+
}
|
45
|
+
|
46
|
+
div#index .section-bar {
|
47
|
+
margin-left: 0px;
|
48
|
+
padding-left: 0.7em;
|
49
|
+
background: #ccc;
|
50
|
+
font-size: small;
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
div#classHeader, div#fileHeader {
|
55
|
+
width: auto;
|
56
|
+
color: white;
|
57
|
+
padding: 0.5em 1.5em 0.5em 1.5em;
|
58
|
+
margin: 0;
|
59
|
+
margin-left: -40px;
|
60
|
+
border-bottom: 3px solid #006;
|
61
|
+
}
|
62
|
+
|
63
|
+
div#classHeader a, div#fileHeader a {
|
64
|
+
background: inherit;
|
65
|
+
color: white;
|
66
|
+
}
|
67
|
+
|
68
|
+
div#classHeader td, div#fileHeader td {
|
69
|
+
background: inherit;
|
70
|
+
color: white;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
div#fileHeader {
|
75
|
+
background: #057;
|
76
|
+
}
|
77
|
+
|
78
|
+
div#classHeader {
|
79
|
+
background: #048;
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
.class-name-in-header {
|
84
|
+
font-size: 180%;
|
85
|
+
font-weight: bold;
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
div#bodyContent {
|
90
|
+
padding: 0 1.5em 0 1.5em;
|
91
|
+
}
|
92
|
+
|
93
|
+
div#description {
|
94
|
+
padding: 0.5em 1.5em;
|
95
|
+
background: #efefef;
|
96
|
+
border: 1px dotted #999;
|
97
|
+
}
|
98
|
+
|
99
|
+
div#description h1,h2,h3,h4,h5,h6 {
|
100
|
+
color: #125;;
|
101
|
+
background: transparent;
|
102
|
+
}
|
103
|
+
|
104
|
+
div#validator-badges {
|
105
|
+
text-align: center;
|
106
|
+
}
|
107
|
+
div#validator-badges img { border: 0; }
|
108
|
+
|
109
|
+
div#copyright {
|
110
|
+
color: #333;
|
111
|
+
background: #efefef;
|
112
|
+
font: 0.75em sans-serif;
|
113
|
+
margin-top: 5em;
|
114
|
+
margin-bottom: 0;
|
115
|
+
padding: 0.5em 2em;
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
/* === Classes =================================== */
|
120
|
+
|
121
|
+
table.header-table {
|
122
|
+
color: white;
|
123
|
+
font-size: small;
|
124
|
+
}
|
125
|
+
|
126
|
+
.type-note {
|
127
|
+
font-size: small;
|
128
|
+
color: #DEDEDE;
|
129
|
+
}
|
130
|
+
|
131
|
+
.xxsection-bar {
|
132
|
+
background: #eee;
|
133
|
+
color: #333;
|
134
|
+
padding: 3px;
|
135
|
+
}
|
136
|
+
|
137
|
+
.section-bar {
|
138
|
+
color: #333;
|
139
|
+
border-bottom: 1px solid #999;
|
140
|
+
margin-left: -20px;
|
141
|
+
}
|
142
|
+
|
143
|
+
|
144
|
+
.section-title {
|
145
|
+
background: #79a;
|
146
|
+
color: #eee;
|
147
|
+
padding: 3px;
|
148
|
+
margin-top: 2em;
|
149
|
+
margin-left: -30px;
|
150
|
+
border: 1px solid #999;
|
151
|
+
}
|
152
|
+
|
153
|
+
.top-aligned-row { vertical-align: top }
|
154
|
+
.bottom-aligned-row { vertical-align: bottom }
|
155
|
+
|
156
|
+
/* --- Context section classes ----------------------- */
|
157
|
+
|
158
|
+
.context-row { }
|
159
|
+
.context-item-name { font-family: monospace; font-weight: bold; color: black; }
|
160
|
+
.context-item-value { font-size: small; color: #448; }
|
161
|
+
.context-item-desc { color: #333; padding-left: 2em; }
|
162
|
+
|
163
|
+
/* --- Method classes -------------------------- */
|
164
|
+
.method-detail {
|
165
|
+
background: #efefef;
|
166
|
+
padding: 0;
|
167
|
+
margin-top: 0.5em;
|
168
|
+
margin-bottom: 1em;
|
169
|
+
border: 1px dotted #ccc;
|
170
|
+
}
|
171
|
+
.method-heading {
|
172
|
+
color: black;
|
173
|
+
background: #ccc;
|
174
|
+
border-bottom: 1px solid #666;
|
175
|
+
padding: 0.2em 0.5em 0 0.5em;
|
176
|
+
}
|
177
|
+
.method-signature { color: black; background: inherit; }
|
178
|
+
.method-name { font-weight: bold; }
|
179
|
+
.method-args { font-style: italic; }
|
180
|
+
.method-description { padding: 0 0.5em 0 0.5em; }
|
181
|
+
|
182
|
+
/* --- Source code sections -------------------- */
|
183
|
+
|
184
|
+
a.source-toggle { font-size: 90%; }
|
185
|
+
div.method-source-code {
|
186
|
+
background: #262626;
|
187
|
+
color: #ffdead;
|
188
|
+
margin: 1em;
|
189
|
+
padding: 0.5em;
|
190
|
+
border: 1px dashed #999;
|
191
|
+
overflow: hidden;
|
192
|
+
}
|
193
|
+
|
194
|
+
div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
195
|
+
|
196
|
+
/* --- Ruby keyword styles --------------------- */
|
197
|
+
|
198
|
+
.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
|
199
|
+
|
200
|
+
.ruby-constant { color: #7fffd4; background: transparent; }
|
201
|
+
.ruby-keyword { color: #00ffff; background: transparent; }
|
202
|
+
.ruby-ivar { color: #eedd82; background: transparent; }
|
203
|
+
.ruby-operator { color: #00ffee; background: transparent; }
|
204
|
+
.ruby-identifier { color: #ffdead; background: transparent; }
|
205
|
+
.ruby-node { color: #ffa07a; background: transparent; }
|
206
|
+
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
|
207
|
+
.ruby-regexp { color: #ffa07a; background: transparent; }
|
208
|
+
.ruby-value { color: #7fffd4; background: transparent; }
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# This is a slighly modified version of the XMLUtilityNode from
|
2
|
+
# http://merb.devjavu.com/projects/merb/ticket/95 (has.sox@gmail.com)
|
3
|
+
# It's mainly just adding vowels, as I ht cd wth n vwls :)
|
4
|
+
# This represents the hard part of the work, all I did was change the underlying
|
5
|
+
# parser
|
6
|
+
|
7
|
+
require 'rexml/light/node'
|
8
|
+
require 'rexml/document'
|
9
|
+
|
10
|
+
module Enumerable
|
11
|
+
def group_by
|
12
|
+
inject({}) do |groups, element|
|
13
|
+
(groups[yield(element)] ||= []) << element
|
14
|
+
groups
|
15
|
+
end
|
16
|
+
end if RUBY_VERSION < '1.9'
|
17
|
+
|
18
|
+
def crawl(&block)
|
19
|
+
raise ArgumentError, "no block given" unless block_given?
|
20
|
+
self.each do |v|
|
21
|
+
k = self
|
22
|
+
v = case block.arity
|
23
|
+
when 1
|
24
|
+
yield(v)
|
25
|
+
when 2
|
26
|
+
yield(k,v)
|
27
|
+
when 3
|
28
|
+
yield(self,k,v)
|
29
|
+
end
|
30
|
+
if v.is_a?(Array)
|
31
|
+
v.crawl(&block)
|
32
|
+
elsif v.is_a?(Hash)
|
33
|
+
v.crawl(&block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class REXMLUtilityNode # :nodoc:
|
40
|
+
attr_accessor :name, :attributes, :children
|
41
|
+
|
42
|
+
def initialize(name, attributes = {})
|
43
|
+
@name = name.tr("-", "_")
|
44
|
+
@attributes = undasherize_keys(attributes)
|
45
|
+
@children = []
|
46
|
+
@text = false
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_node(node)
|
50
|
+
@text = true if node.is_a? String
|
51
|
+
@children << node
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_hash
|
55
|
+
if @text
|
56
|
+
return { name => typecast_value( translate_xml_entities( inner_html ) ) }
|
57
|
+
else
|
58
|
+
#change repeating groups into an array
|
59
|
+
# group by the first key of each element of the array to find repeating groups
|
60
|
+
groups = @children.group_by{ |c| c.name }
|
61
|
+
|
62
|
+
hash = {}
|
63
|
+
groups.each do |key, values|
|
64
|
+
if values.size == 1
|
65
|
+
hash.merge! values.first
|
66
|
+
else
|
67
|
+
hash.merge! key => values.map { |element| element.to_hash[key] }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# merge the arrays, including attributes
|
72
|
+
hash.merge! attributes unless attributes.empty?
|
73
|
+
|
74
|
+
{ name => hash }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def typecast_value(value)
|
79
|
+
return value unless attributes["type"]
|
80
|
+
|
81
|
+
case attributes["type"]
|
82
|
+
when "integer" then value.to_i
|
83
|
+
when "boolean" then value.strip == "true"
|
84
|
+
when "datetime" then ::Time.parse(value).utc
|
85
|
+
when "date" then ::Date.parse(value)
|
86
|
+
else value
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def translate_xml_entities(value)
|
91
|
+
value.gsub(/</, "<").
|
92
|
+
gsub(/>/, ">").
|
93
|
+
gsub(/"/, '"').
|
94
|
+
gsub(/'/, "'").
|
95
|
+
gsub(/&/, "&")
|
96
|
+
end
|
97
|
+
|
98
|
+
def undasherize_keys(params)
|
99
|
+
params.keys.each do |key, vvalue|
|
100
|
+
params[key.tr("-", "_")] = params.delete(key)
|
101
|
+
end
|
102
|
+
params
|
103
|
+
end
|
104
|
+
|
105
|
+
def inner_html
|
106
|
+
@children.join
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_html
|
110
|
+
"<#{name}#{attributes.to_xml_attributes}>#{inner_html}</#{name}>"
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_s
|
114
|
+
to_html
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
module FormattedString
|
119
|
+
module Formats
|
120
|
+
module Xml
|
121
|
+
XML_OPTIONS = {
|
122
|
+
:include_key => :attribute, # Can be false, :element, or :attribute
|
123
|
+
:report_nil => true, # Sets an attribute nil="true" on elements that are nil, so that the reader doesn't read as an empty string
|
124
|
+
:key_name => 'id', # Default key name
|
125
|
+
}
|
126
|
+
|
127
|
+
def to_hash(options={})
|
128
|
+
options = XML_OPTIONS.merge(options)
|
129
|
+
|
130
|
+
stack = []
|
131
|
+
parser = REXML::Parsers::BaseParser.new(self)
|
132
|
+
|
133
|
+
while true
|
134
|
+
event = parser.pull
|
135
|
+
case event[0]
|
136
|
+
when :end_document
|
137
|
+
break
|
138
|
+
when :end_doctype, :start_doctype
|
139
|
+
# do nothing
|
140
|
+
when :start_element
|
141
|
+
stack.push REXMLUtilityNode.new(event[1], event[2])
|
142
|
+
when :end_element
|
143
|
+
if stack.size > 1
|
144
|
+
temp = stack.pop
|
145
|
+
stack.last.add_node(temp)
|
146
|
+
end
|
147
|
+
when :text, :cdata
|
148
|
+
stack.last.add_node(event[1]) unless event[1].strip.length == 0
|
149
|
+
end
|
150
|
+
end
|
151
|
+
data = stack.pop.to_hash
|
152
|
+
|
153
|
+
# Turn any {} || {"nil" => "true"} into just nil
|
154
|
+
if options[:report_nil]
|
155
|
+
data.crawl {|h,k,v| h[k] = nil if v == {} || v == {'nil' => 'true'}; v}
|
156
|
+
else
|
157
|
+
data.crawl {|h,k,v| h[k] = nil if v == {}; v}
|
158
|
+
end
|
159
|
+
data
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'inflector'
|
2
|
+
|
3
|
+
class String
|
4
|
+
|
5
|
+
# Use this to see what format you've set to the string.
|
6
|
+
# s = '<some><xml>text</xml></some>'
|
7
|
+
# s.format = :xml
|
8
|
+
# s.format
|
9
|
+
# => :xml
|
10
|
+
def format
|
11
|
+
@format
|
12
|
+
end
|
13
|
+
|
14
|
+
# Use this to specify that this string is a certain format.
|
15
|
+
# s = '<some><xml>text</xml></some>'
|
16
|
+
# s.format = :xml
|
17
|
+
# s.to_hash # a method extended onto the `s' object from the xml format module.
|
18
|
+
# => {'some' => {'xml' => 'text'}}
|
19
|
+
def format=(fmat)
|
20
|
+
require "formatted_string/formats/#{fmat.to_s}" rescue nil
|
21
|
+
extend Object.module_eval("::FormattedString::Formats::#{Inflector.camelize(fmat.to_s)}", __FILE__, __LINE__)
|
22
|
+
@format = [@format, fmat].flatten.compact
|
23
|
+
end
|
24
|
+
|
25
|
+
# Simply sets format=, but returns the string object.
|
26
|
+
def formatted(fmat)
|
27
|
+
self.format = fmat
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
# I'd like to eventually make this auto-recognize the format, but I haven't yet had the time.
|
32
|
+
# def auto_recognize_format
|
33
|
+
# end
|
34
|
+
end
|
data/lib/inflections.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
Inflector.inflections do |inflect|
|
2
|
+
inflect.plural(/$/, 's')
|
3
|
+
inflect.plural(/s$/i, 's')
|
4
|
+
inflect.plural(/(ax|test)is$/i, '\1es')
|
5
|
+
inflect.plural(/(octop|vir)us$/i, '\1i')
|
6
|
+
inflect.plural(/(alias|status)$/i, '\1es')
|
7
|
+
inflect.plural(/(bu)s$/i, '\1ses')
|
8
|
+
inflect.plural(/(buffal|tomat)o$/i, '\1oes')
|
9
|
+
inflect.plural(/([ti])um$/i, '\1a')
|
10
|
+
inflect.plural(/sis$/i, 'ses')
|
11
|
+
inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
|
12
|
+
inflect.plural(/(hive)$/i, '\1s')
|
13
|
+
inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
|
14
|
+
inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
|
15
|
+
inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
|
16
|
+
inflect.plural(/([m|l])ouse$/i, '\1ice')
|
17
|
+
inflect.plural(/^(ox)$/i, '\1en')
|
18
|
+
inflect.plural(/(quiz)$/i, '\1zes')
|
19
|
+
|
20
|
+
inflect.singular(/s$/i, '')
|
21
|
+
inflect.singular(/(n)ews$/i, '\1ews')
|
22
|
+
inflect.singular(/([ti])a$/i, '\1um')
|
23
|
+
inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis')
|
24
|
+
inflect.singular(/(^analy)ses$/i, '\1sis')
|
25
|
+
inflect.singular(/([^f])ves$/i, '\1fe')
|
26
|
+
inflect.singular(/(hive)s$/i, '\1')
|
27
|
+
inflect.singular(/(tive)s$/i, '\1')
|
28
|
+
inflect.singular(/([lr])ves$/i, '\1f')
|
29
|
+
inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y')
|
30
|
+
inflect.singular(/(s)eries$/i, '\1eries')
|
31
|
+
inflect.singular(/(m)ovies$/i, '\1ovie')
|
32
|
+
inflect.singular(/(x|ch|ss|sh)es$/i, '\1')
|
33
|
+
inflect.singular(/([m|l])ice$/i, '\1ouse')
|
34
|
+
inflect.singular(/(bus)es$/i, '\1')
|
35
|
+
inflect.singular(/(o)es$/i, '\1')
|
36
|
+
inflect.singular(/(shoe)s$/i, '\1')
|
37
|
+
inflect.singular(/(cris|ax|test)es$/i, '\1is')
|
38
|
+
inflect.singular(/(octop|vir)i$/i, '\1us')
|
39
|
+
inflect.singular(/(alias|status)es$/i, '\1')
|
40
|
+
inflect.singular(/^(ox)en/i, '\1')
|
41
|
+
inflect.singular(/(vert|ind)ices$/i, '\1ex')
|
42
|
+
inflect.singular(/(matr)ices$/i, '\1ix')
|
43
|
+
inflect.singular(/(quiz)zes$/i, '\1')
|
44
|
+
|
45
|
+
inflect.irregular('person', 'people')
|
46
|
+
inflect.irregular('man', 'men')
|
47
|
+
inflect.irregular('child', 'children')
|
48
|
+
inflect.irregular('sex', 'sexes')
|
49
|
+
inflect.irregular('move', 'moves')
|
50
|
+
inflect.irregular('cow', 'kine')
|
51
|
+
|
52
|
+
inflect.uncountable(%w(equipment information rice money species series fish sheep))
|
53
|
+
end
|