caruby-core 1.4.1

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 (86) hide show
  1. data/History.txt +4 -0
  2. data/LEGAL +5 -0
  3. data/LICENSE +22 -0
  4. data/README.md +51 -0
  5. data/doc/website/css/site.css +1 -5
  6. data/doc/website/images/avatar.png +0 -0
  7. data/doc/website/images/favicon.ico +0 -0
  8. data/doc/website/images/logo.png +0 -0
  9. data/doc/website/index.html +82 -0
  10. data/doc/website/install.html +87 -0
  11. data/doc/website/quick_start.html +87 -0
  12. data/doc/website/tissue.html +85 -0
  13. data/doc/website/uom.html +10 -0
  14. data/lib/caruby.rb +3 -0
  15. data/lib/caruby/active_support/README.txt +2 -0
  16. data/lib/caruby/active_support/core_ext/string.rb +7 -0
  17. data/lib/caruby/active_support/core_ext/string/inflections.rb +167 -0
  18. data/lib/caruby/active_support/inflections.rb +55 -0
  19. data/lib/caruby/active_support/inflector.rb +398 -0
  20. data/lib/caruby/cli/application.rb +36 -0
  21. data/lib/caruby/cli/command.rb +169 -0
  22. data/lib/caruby/csv/csv_mapper.rb +157 -0
  23. data/lib/caruby/csv/csvio.rb +185 -0
  24. data/lib/caruby/database.rb +252 -0
  25. data/lib/caruby/database/fetched_matcher.rb +66 -0
  26. data/lib/caruby/database/persistable.rb +432 -0
  27. data/lib/caruby/database/persistence_service.rb +162 -0
  28. data/lib/caruby/database/reader.rb +599 -0
  29. data/lib/caruby/database/saved_merger.rb +131 -0
  30. data/lib/caruby/database/search_template_builder.rb +59 -0
  31. data/lib/caruby/database/sql_executor.rb +75 -0
  32. data/lib/caruby/database/store_template_builder.rb +200 -0
  33. data/lib/caruby/database/writer.rb +469 -0
  34. data/lib/caruby/domain/annotatable.rb +25 -0
  35. data/lib/caruby/domain/annotation.rb +23 -0
  36. data/lib/caruby/domain/attribute_metadata.rb +447 -0
  37. data/lib/caruby/domain/java_attribute_metadata.rb +160 -0
  38. data/lib/caruby/domain/merge.rb +91 -0
  39. data/lib/caruby/domain/properties.rb +95 -0
  40. data/lib/caruby/domain/reference_visitor.rb +289 -0
  41. data/lib/caruby/domain/resource_attributes.rb +528 -0
  42. data/lib/caruby/domain/resource_dependency.rb +205 -0
  43. data/lib/caruby/domain/resource_introspection.rb +159 -0
  44. data/lib/caruby/domain/resource_metadata.rb +117 -0
  45. data/lib/caruby/domain/resource_module.rb +285 -0
  46. data/lib/caruby/domain/uniquify.rb +38 -0
  47. data/lib/caruby/import/annotatable_class.rb +28 -0
  48. data/lib/caruby/import/annotation_class.rb +27 -0
  49. data/lib/caruby/import/annotation_module.rb +67 -0
  50. data/lib/caruby/import/java.rb +338 -0
  51. data/lib/caruby/migration/migratable.rb +167 -0
  52. data/lib/caruby/migration/migrator.rb +533 -0
  53. data/lib/caruby/migration/resource.rb +8 -0
  54. data/lib/caruby/migration/resource_module.rb +11 -0
  55. data/lib/caruby/migration/uniquify.rb +20 -0
  56. data/lib/caruby/resource.rb +969 -0
  57. data/lib/caruby/util/attribute_path.rb +46 -0
  58. data/lib/caruby/util/cache.rb +53 -0
  59. data/lib/caruby/util/class.rb +99 -0
  60. data/lib/caruby/util/collection.rb +1053 -0
  61. data/lib/caruby/util/controlled_value.rb +35 -0
  62. data/lib/caruby/util/coordinate.rb +75 -0
  63. data/lib/caruby/util/domain_extent.rb +49 -0
  64. data/lib/caruby/util/file_separator.rb +65 -0
  65. data/lib/caruby/util/inflector.rb +20 -0
  66. data/lib/caruby/util/log.rb +95 -0
  67. data/lib/caruby/util/math.rb +12 -0
  68. data/lib/caruby/util/merge.rb +59 -0
  69. data/lib/caruby/util/module.rb +34 -0
  70. data/lib/caruby/util/options.rb +92 -0
  71. data/lib/caruby/util/partial_order.rb +36 -0
  72. data/lib/caruby/util/person.rb +119 -0
  73. data/lib/caruby/util/pretty_print.rb +184 -0
  74. data/lib/caruby/util/properties.rb +112 -0
  75. data/lib/caruby/util/stopwatch.rb +66 -0
  76. data/lib/caruby/util/topological_sync_enumerator.rb +53 -0
  77. data/lib/caruby/util/transitive_closure.rb +45 -0
  78. data/lib/caruby/util/tree.rb +48 -0
  79. data/lib/caruby/util/trie.rb +37 -0
  80. data/lib/caruby/util/uniquifier.rb +30 -0
  81. data/lib/caruby/util/validation.rb +48 -0
  82. data/lib/caruby/util/version.rb +56 -0
  83. data/lib/caruby/util/visitor.rb +351 -0
  84. data/lib/caruby/util/weak_hash.rb +36 -0
  85. data/lib/caruby/version.rb +3 -0
  86. metadata +186 -0
@@ -0,0 +1,10 @@
1
+ UOM implements Units of Measurement based on the
2
+ <a href=http://physics.nist.gov/Pubs/SP330/sp330.pdf>International System of Units (SI)</a>.
3
+ The base SI units, metric scalar factors and all possible combinations of these units are supported out of the box.
4
+
5
+ Common alternative non-metric measurement systems, e.g. US Customary units, are supported with conversions between
6
+ these units and the SI units. Additional units can be defined with conversion to an existing unit. UOM infers
7
+ full conversion capability between units of the same dimension from the minimal number of conversion definitions.
8
+
9
+ Arithmetic operations between UOM Measurement objects converts the measurement units and scalar factors as necessary,
10
+ including unit products, quotients and powers of arbitrary complexity.
data/lib/caruby.rb ADDED
@@ -0,0 +1,3 @@
1
+ # CaRuby is a JRuby facade for the caBIG application APIs.
2
+ # See the [http://http://caruby.rubyforge.org/](caRuby) home page for more information.
3
+ module CaRuby;end
@@ -0,0 +1,2 @@
1
+ The files in this directory are shamelessly stolen from Rails. They are included here rather than pulled in as a gem
2
+ in order to avoid a dependency on the entire Rails project for a limited utility.
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ require 'active_support/core_ext/string/inflections'
4
+
5
+ class String #:nodoc:
6
+ include ActiveSupport::CoreExtensions::String::Inflections
7
+ end
@@ -0,0 +1,167 @@
1
+ require 'caruby/active_support/inflector'
2
+
3
+ module ActiveSupport #:nodoc:
4
+ module CoreExtensions #:nodoc:
5
+ module String #:nodoc:
6
+ # String inflections define new methods on the String class to transform names for different purposes.
7
+ # For instance, you can figure out the name of a database from the name of a class.
8
+ #
9
+ # "ScaleScore".tableize #=>"scale_scores"
10
+ module Inflections
11
+ # Returns the plural form of the word in the string.
12
+ #
13
+ # "post".pluralize #=>"posts"
14
+ # "octopus".pluralize #=>"octopi"
15
+ # "sheep".pluralize #=>"sheep"
16
+ # "words".pluralize #=>"words"
17
+ # "the blue mailman".pluralize #=>"the blue mailmen"
18
+ # "CamelOctopus".pluralize #=>"CamelOctopi"
19
+ def pluralize
20
+ Inflector.pluralize(self)
21
+ end
22
+
23
+ # The reverse of +pluralize+, returns the singular form of a word in a string.
24
+ #
25
+ # "posts".singularize #=>"post"
26
+ # "octopi".singularize #=>"octopus"
27
+ # "sheep".singularize #=>"sheep"
28
+ # "word".singularize #=>"word"
29
+ # "the blue mailmen".singularize #=>"the blue mailman"
30
+ # "CamelOctopi".singularize #=>"CamelOctopus"
31
+ def singularize
32
+ Inflector.singularize(self)
33
+ end
34
+
35
+ # By default, +camelize+ converts strings to UpperCamelCase. If the argument to camelize
36
+ # is set to <tt>:lower</tt> then camelize produces lowerCamelCase.
37
+ #
38
+ # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
39
+ #
40
+ # "active_record".camelize #=>"ActiveRecord"
41
+ # "active_record".camelize(:lower) #=>"activeRecord"
42
+ # "active_record/errors".camelize #=>"ActiveRecord::Errors"
43
+ # "active_record/errors".camelize(:lower) #=>"activeRecord::Errors"
44
+ def camelize(first_letter = :upper)
45
+ case first_letter
46
+ when :upper then Inflector.camelize(self, true)
47
+ when :lower then Inflector.camelize(self, false)
48
+ end
49
+ end
50
+ alias_method :camelcase, :camelize
51
+
52
+ # Capitalizes all the words and replaces some characters in the string to create
53
+ # a nicer looking title. +titleize+ is meant for creating pretty output. It is not
54
+ # used in the Rails internals.
55
+ #
56
+ # +titleize+ is also aliased as +titlecase+.
57
+ #
58
+ # "man from the boondocks".titleize #=>"Man From The Boondocks"
59
+ # "x-men: the last stand".titleize #=>"X Men: The Last Stand"
60
+ def titleize
61
+ Inflector.titleize(self)
62
+ end
63
+ alias_method :titlecase, :titleize
64
+
65
+ # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
66
+ #
67
+ # +underscore+ will also change '::' to '/' to convert namespaces to paths.
68
+ #
69
+ # "ActiveRecord".underscore #=>"active_record"
70
+ # "ActiveRecord::Errors".underscore #=>active_record/errors
71
+ def underscore
72
+ Inflector.underscore(self)
73
+ end
74
+
75
+ # Replaces underscores with dashes in the string.
76
+ #
77
+ # "puni_puni" #=>"puni-puni"
78
+ def dasherize
79
+ Inflector.dasherize(self)
80
+ end
81
+
82
+ # Removes the module part from the constant expression in the string.
83
+ #
84
+ # "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=>"Inflections"
85
+ # "Inflections".demodulize #=>"Inflections"
86
+ def demodulize
87
+ Inflector.demodulize(self)
88
+ end
89
+
90
+ # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
91
+ #
92
+ # ==== Examples
93
+ #
94
+ # class Person
95
+ # def to_param
96
+ # "#{id}-#{name.parameterize}"
97
+ # end
98
+ # end
99
+ #
100
+ # @person = Person.find(1)
101
+ # #=>#<Person id: 1, name: "Donald E. Knuth">
102
+ #
103
+ # <%= link_to(@person.name, person_path %>
104
+ # #=><a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
105
+ def parameterize
106
+ Inflector.parameterize(self)
107
+ end
108
+
109
+ # Creates the name of a table like Rails does for models to table names. This method
110
+ # uses the +pluralize+ method on the last word in the string.
111
+ #
112
+ # "RawScaledScorer".tableize #=>"raw_scaled_scorers"
113
+ # "egg_and_ham".tableize #=>"egg_and_hams"
114
+ # "fancyCategory".tableize #=>"fancy_categories"
115
+ def tableize
116
+ Inflector.tableize(self)
117
+ end
118
+
119
+ # Create a class name from a plural table name like Rails does for table names to models.
120
+ # Note that this returns a string and not a class. (To convert to an actual class
121
+ # follow +classify+ with +constantize+.)
122
+ #
123
+ # "egg_and_hams".classify #=>"EggAndHam"
124
+ # "posts".classify #=>"Post"
125
+ #
126
+ # Singular names are not handled correctly.
127
+ #
128
+ # "business".classify #=>"Busines"
129
+ def classify
130
+ Inflector.classify(self)
131
+ end
132
+
133
+ # Capitalizes the first word, turns underscores into spaces, and strips '_id'.
134
+ # Like +titleize+, this is meant for creating pretty output.
135
+ #
136
+ # "employee_salary" #=>"Employee salary"
137
+ # "author_id" #=>"Author"
138
+ def humanize
139
+ Inflector.humanize(self)
140
+ end
141
+
142
+ # Creates a foreign key name from a class name.
143
+ # +separate_class_name_and_id_with_underscore+ sets whether
144
+ # the method should put '_' between the name and 'id'.
145
+ #
146
+ # Examples
147
+ # "Message".foreign_key #=>"message_id"
148
+ # "Message".foreign_key(false) #=>"messageid"
149
+ # "Admin::Post".foreign_key #=>"post_id"
150
+ def foreign_key(separate_class_name_and_id_with_underscore = true)
151
+ Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
152
+ end
153
+
154
+ # +constantize+ tries to find a declared constant with the name specified
155
+ # in the string. It raises a NameError when the name is not in CamelCase
156
+ # or is not initialized.
157
+ #
158
+ # Examples
159
+ # "Module".constantize #=>Module
160
+ # "Class".constantize #=>Class
161
+ def constantize
162
+ Inflector.constantize(self)
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,55 @@
1
+ module ActiveSupport
2
+ Inflector.inflections do |inflect|
3
+ inflect.plural(/$/, 's')
4
+ inflect.plural(/s$/i, 's')
5
+ inflect.plural(/(ax|test)is$/i, '\1es')
6
+ inflect.plural(/(octop|vir)us$/i, '\1i')
7
+ inflect.plural(/(alias|status)$/i, '\1es')
8
+ inflect.plural(/(bu)s$/i, '\1ses')
9
+ inflect.plural(/(buffal|tomat)o$/i, '\1oes')
10
+ inflect.plural(/([ti])um$/i, '\1a')
11
+ inflect.plural(/sis$/i, 'ses')
12
+ inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
13
+ inflect.plural(/(hive)$/i, '\1s')
14
+ inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
15
+ inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
16
+ inflect.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
17
+ inflect.plural(/([m|l])ouse$/i, '\1ice')
18
+ inflect.plural(/^(ox)$/i, '\1en')
19
+ inflect.plural(/(quiz)$/i, '\1zes')
20
+
21
+ inflect.singular(/s$/i, '')
22
+ inflect.singular(/(n)ews$/i, '\1ews')
23
+ inflect.singular(/([ti])a$/i, '\1um')
24
+ inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis')
25
+ inflect.singular(/(^analy)ses$/i, '\1sis')
26
+ inflect.singular(/([^f])ves$/i, '\1fe')
27
+ inflect.singular(/(hive)s$/i, '\1')
28
+ inflect.singular(/(tive)s$/i, '\1')
29
+ inflect.singular(/([lr])ves$/i, '\1f')
30
+ inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y')
31
+ inflect.singular(/(s)eries$/i, '\1eries')
32
+ inflect.singular(/(m)ovies$/i, '\1ovie')
33
+ inflect.singular(/(x|ch|ss|sh)es$/i, '\1')
34
+ inflect.singular(/([m|l])ice$/i, '\1ouse')
35
+ inflect.singular(/(bus)es$/i, '\1')
36
+ inflect.singular(/(o)es$/i, '\1')
37
+ inflect.singular(/(shoe)s$/i, '\1')
38
+ inflect.singular(/(cris|ax|test)es$/i, '\1is')
39
+ inflect.singular(/(octop|vir)i$/i, '\1us')
40
+ inflect.singular(/(alias|status)es$/i, '\1')
41
+ inflect.singular(/^(ox)en/i, '\1')
42
+ inflect.singular(/(vert|ind)ices$/i, '\1ex')
43
+ inflect.singular(/(matr)ices$/i, '\1ix')
44
+ inflect.singular(/(quiz)zes$/i, '\1')
45
+
46
+ inflect.irregular('person', 'people')
47
+ inflect.irregular('man', 'men')
48
+ inflect.irregular('child', 'children')
49
+ inflect.irregular('sex', 'sexes')
50
+ inflect.irregular('move', 'moves')
51
+ inflect.irregular('cow', 'kine')
52
+
53
+ inflect.uncountable(%w(equipment information rice money species series fish sheep))
54
+ end
55
+ end
@@ -0,0 +1,398 @@
1
+ # encoding: utf-8
2
+ require 'singleton'
3
+ require 'iconv'
4
+
5
+ module ActiveSupport
6
+ # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
7
+ # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
8
+ # in inflections.rb.
9
+ #
10
+ # The Rails core team has stated patches for the inflections library will not be accepted
11
+ # in order to avoid breaking legacy applications which may be relying on errant inflections.
12
+ # If you discover an incorrect inflection and require it for your application, you'll need
13
+ # to correct it yourself (explained below).
14
+ module Inflector
15
+ extend self
16
+
17
+ # A singleton instance of this class is yielded by {Inflector#inflections}, which can then be used to specify additional
18
+ # inflection rules. Examples:
19
+ #
20
+ # ActiveSupport::Inflector.inflections do |inflect|
21
+ # inflect.plural /^(ox)$/i, '\12en'
22
+ # inflect.singular /^(ox)en/i, '1'
23
+ #
24
+ # inflect.irregular 'octopus', 'octopi'
25
+ #
26
+ # inflect.uncountable "equipment"
27
+ # end
28
+ #
29
+ # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
30
+ # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
31
+ # already have been loaded.
32
+ class Inflections
33
+ include Singleton
34
+
35
+ attr_reader :plurals, :singulars, :uncountables, :humans
36
+
37
+ def initialize
38
+ @plurals, @singulars, @uncountables, @humans = [], [], [], []
39
+ end
40
+
41
+ # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
42
+ # The replacement should always be a string that may include references to the matched data from the rule.
43
+ def plural(rule, replacement)
44
+ @uncountables.delete(rule) if String === rule
45
+ @uncountables.delete(replacement)
46
+ @plurals.insert(0, [rule, replacement])
47
+ end
48
+
49
+ # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
50
+ # The replacement should always be a string that may include references to the matched data from the rule.
51
+ def singular(rule, replacement)
52
+ @uncountables.delete(rule) if String === rule
53
+ @uncountables.delete(replacement)
54
+ @singulars.insert(0, [rule, replacement])
55
+ end
56
+
57
+ # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
58
+ # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
59
+ #
60
+ # @example
61
+ # irregular 'octopus', 'octopi'
62
+ # irregular 'person', 'people'
63
+ def irregular(singular, plural)
64
+ @uncountables.delete(singular)
65
+ @uncountables.delete(plural)
66
+ if singular[0,1].upcase == plural[0,1].upcase
67
+ plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
68
+ singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
69
+ else
70
+ plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
71
+ plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
72
+ singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1])
73
+ singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1])
74
+ end
75
+ end
76
+
77
+ # Add uncountable words that shouldn't be attempted inflected.
78
+ #
79
+ # @example
80
+ # uncountable "money"
81
+ # uncountable "money", "information"
82
+ # uncountable %w( money information rice )
83
+ def uncountable(*words)
84
+ (@uncountables << words).flatten!
85
+ end
86
+
87
+ # Specifies a humanized form of a string by a regular expression rule or by a string mapping.
88
+ # When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
89
+ # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
90
+ #
91
+ # @example
92
+ # human /_cnt$/i, '1_count'
93
+ # human "legacy_col_person_name", "Name"
94
+ def human(rule, replacement)
95
+ @humans.insert(0, [rule, replacement])
96
+ end
97
+
98
+ # Clears the loaded inflections within a given scope (default is <tt>:all</tt>).
99
+ # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>,
100
+ # <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>.
101
+ #
102
+ # @example
103
+ # clear :all
104
+ # clear :plurals
105
+ def clear(scope = :all)
106
+ case scope
107
+ when :all
108
+ @plurals, @singulars, @uncountables = [], [], []
109
+ else
110
+ instance_variable_set "@#{scope}", []
111
+ end
112
+ end
113
+ end
114
+
115
+ # Yields a singleton instance of Inflector::Inflections so you can specify additional
116
+ # inflector rules.
117
+ #
118
+ # Example:
119
+ # ActiveSupport::Inflector.inflections do |inflect|
120
+ # inflect.uncountable "rails"
121
+ # end
122
+ def inflections
123
+ if block_given?
124
+ yield Inflections.instance
125
+ else
126
+ Inflections.instance
127
+ end
128
+ end
129
+
130
+ # Returns the plural form of the word in the string.
131
+ #
132
+ # @example
133
+ # "post".pluralize #=>"posts"
134
+ # "octopus".pluralize #=>"octopi"
135
+ # "sheep".pluralize #=>"sheep"
136
+ # "words".pluralize #=>"words"
137
+ # "CamelOctopus".pluralize #=>"CamelOctopi"
138
+ def pluralize(word)
139
+ result = word.to_s.dup
140
+
141
+ if word.empty? || inflections.uncountables.include?(result.downcase)
142
+ result
143
+ else
144
+ inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
145
+ result
146
+ end
147
+ end
148
+
149
+ # The reverse of +pluralize+, returns the singular form of a word in a string.
150
+ #
151
+ # @example
152
+ # "posts".singularize #=>"post"
153
+ # "octopi".singularize #=>"octopus"
154
+ # "sheep".singluarize #=>"sheep"
155
+ # "word".singularize #=>"word"
156
+ # "CamelOctopi".singularize #=>"CamelOctopus"
157
+ def singularize(word)
158
+ result = word.to_s.dup
159
+
160
+ if inflections.uncountables.include?(result.downcase)
161
+ result
162
+ else
163
+ inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
164
+ result
165
+ end
166
+ end
167
+
168
+ # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
169
+ # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
170
+ #
171
+ # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
172
+ #
173
+ # @example
174
+ # "active_record".camelize #=>"ActiveRecord"
175
+ # "active_record".camelize(:lower) #=>"activeRecord"
176
+ # "active_record/errors".camelize #=>"ActiveRecord::Errors"
177
+ # "active_record/errors".camelize(:lower) #=>"activeRecord::Errors"
178
+ def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
179
+ if first_letter_in_uppercase
180
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase }" }.gsub(/(?:^|_)(.)/) { $1.upcase }
181
+ else
182
+ # FL - fixed bug: String doesn't have a first method
183
+ #lower_case_and_underscored_word.first.downcase + camelize(lower_case_and_underscored_word)[1..-1]
184
+ lower_case_and_underscored_word[0, 1].downcase + camelize(lower_case_and_underscored_word)[1..-1]
185
+ end
186
+ end
187
+
188
+ # Capitalizes all the words and replaces some characters in the string to create
189
+ # a nicer looking title. +titleize+ is meant for creating pretty output. It is not
190
+ # used in the Rails internals.
191
+ #
192
+ # +titleize+ is also aliased as as +titlecase+.
193
+ #
194
+ # Examples:
195
+ # "man from the boondocks".titleize #=>"Man From The Boondocks"
196
+ # "x-men: the last stand".titleize #=>"X Men: The Last Stand"
197
+ def titleize(word)
198
+ humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
199
+ end
200
+
201
+ # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
202
+ #
203
+ # Changes '::' to '/' to convert namespaces to paths.
204
+ #
205
+ # Examples:
206
+ # "ActiveRecord".underscore #=>"active_record"
207
+ # "ActiveRecord::Errors".underscore #=>active_record/errors
208
+ def underscore(camel_cased_word)
209
+ camel_cased_word.to_s.gsub(/::/, '/').
210
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
211
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
212
+ tr("-", "_").
213
+ downcase
214
+ end
215
+
216
+ # Replaces underscores with dashes in the string.
217
+ #
218
+ # Example:
219
+ # "puni_puni" #=>"puni-puni"
220
+ def dasherize(underscored_word)
221
+ underscored_word.gsub(/_/, '-')
222
+ end
223
+
224
+ # Capitalizes the first word and turns underscores into spaces and strips a
225
+ # trailing "_id", if any. Like +titleize+, this is meant for creating pretty output.
226
+ #
227
+ # Examples:
228
+ # "employee_salary" #=>"Employee salary"
229
+ # "author_id" #=>"Author"
230
+ def humanize(lower_case_and_underscored_word)
231
+ result = lower_case_and_underscored_word.to_s.dup
232
+
233
+ inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
234
+ result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
235
+ end
236
+
237
+ # Removes the module part from the expression in the string.
238
+ #
239
+ # Examples:
240
+ # "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=>"Inflections"
241
+ # "Inflections".demodulize #=>"Inflections"
242
+ def demodulize(class_name_in_module)
243
+ class_name_in_module.to_s.gsub(/^.*::/, '')
244
+ end
245
+
246
+ # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
247
+ #
248
+ # ==== Examples
249
+ #
250
+ # class Person
251
+ # def to_param
252
+ # "#{id}-#{name.parameterize}"
253
+ # end
254
+ # end
255
+ #
256
+ # @person = Person.find(1)
257
+ # #=>#<Person id: 1, name: "Donald E. Knuth">
258
+ #
259
+ # <%= link_to(@person.name, person_path %>
260
+ # #=><a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
261
+ def parameterize(string, sep = '-')
262
+ re_sep = Regexp.escape(sep)
263
+ # replace accented chars with ther ascii equivalents
264
+ parameterized_string = transliterate(string)
265
+ # Turn unwanted chars into the seperator
266
+ parameterized_string.gsub!(/[^a-z0-9\-_\+]+/i, sep)
267
+ # No more than one of the separator in a row.
268
+ parameterized_string.squeeze!(sep)
269
+ # Remove leading/trailing separator.
270
+ parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '')
271
+ parameterized_string.downcase
272
+ end
273
+
274
+ # Replaces accented characters with their ascii equivalents.
275
+ def transliterate(string)
276
+ Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s
277
+ end
278
+
279
+ # The iconv transliteration code doesn't function correctly
280
+ # on some platforms, but it's very fast where it does function.
281
+ if "foo" != Inflector.transliterate("föö")
282
+ undef_method :transliterate
283
+ def transliterate(string)
284
+ string.mb_chars.normalize(:kd). # Decompose accented characters
285
+ gsub(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics).
286
+ end
287
+ end
288
+
289
+ # Create the name of a table like Rails does for models to table names. This method
290
+ # uses the +pluralize+ method on the last word in the string.
291
+ #
292
+ # Examples
293
+ # "RawScaledScorer".tableize #=>"raw_scaled_scorers"
294
+ # "egg_and_ham".tableize #=>"egg_and_hams"
295
+ # "fancyCategory".tableize #=>"fancy_categories"
296
+ def tableize(class_name)
297
+ pluralize(underscore(class_name))
298
+ end
299
+
300
+ # Create a class name from a plural table name like Rails does for table names to models.
301
+ # Note that this returns a string and not a Class. (To convert to an actual class
302
+ # follow +classify+ with +constantize+.)
303
+ #
304
+ # Examples:
305
+ # "egg_and_hams".classify #=>"EggAndHam"
306
+ # "posts".classify #=>"Post"
307
+ #
308
+ # Singular names are not handled correctly:
309
+ # "business".classify #=>"Busines"
310
+ def classify(table_name)
311
+ # strip out any leading schema name
312
+ camelize(singularize(table_name.to_s.sub(/.*\./, '')))
313
+ end
314
+
315
+ # Creates a foreign key name from a class name.
316
+ # +separate_class_name_and_id_with_underscore+ sets whether
317
+ # the method should put '_' between the name and 'id'.
318
+ #
319
+ # Examples:
320
+ # "Message".foreign_key #=>"message_id"
321
+ # "Message".foreign_key(false) #=>"messageid"
322
+ # "Admin::Post".foreign_key #=>"post_id"
323
+ def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
324
+ underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
325
+ end
326
+
327
+ # Ruby 1.9 introduces an inherit argument for {Module#const_get} and
328
+ # #const_defined? and changes their default behavior.
329
+ if Module.method(:const_get).arity == 1
330
+ # Tries to find a constant with the name specified in the argument string:
331
+ #
332
+ # "Module".constantize #=>Module
333
+ # "Test::Unit".constantize #=>Test::Unit
334
+ #
335
+ # The name is assumed to be the one of a top-level constant, no matter whether
336
+ # it starts with "::" or not. No lexical context is taken into account:
337
+ #
338
+ # C = 'outside'
339
+ # module M
340
+ # C = 'inside'
341
+ # C #=>'inside'
342
+ # "C".constantize #=>'outside', same as ::C
343
+ # end
344
+ #
345
+ # NameError is raised when the name is not in CamelCase or the constant is
346
+ # unknown.
347
+ def constantize(camel_cased_word)
348
+ names = camel_cased_word.split('::')
349
+ names.shift if names.empty? || names.first.empty?
350
+
351
+ constant = Object
352
+ names.each do |name|
353
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
354
+ end
355
+ constant
356
+ end
357
+ else
358
+ def constantize(camel_cased_word) #:nodoc:
359
+ names = camel_cased_word.split('::')
360
+ names.shift if names.empty? || names.first.empty?
361
+
362
+ constant = Object
363
+ names.each do |name|
364
+ constant = constant.const_get(name, false) || constant.const_missing(name)
365
+ end
366
+ constant
367
+ end
368
+ end
369
+
370
+ # Turns a number into an ordinal string used to denote the position in an
371
+ # ordered sequence such as 1st, 2nd, 3rd, 4th.
372
+ #
373
+ # Examples:
374
+ # ordinalize(1) #=>"1st"
375
+ # ordinalize(2) #=>"2nd"
376
+ # ordinalize(1002) #=>"1002nd"
377
+ # ordinalize(1003) #=>"1003rd"
378
+ def ordinalize(number)
379
+ if (11..13).include?(number.to_i % 100)
380
+ "#{number}th"
381
+ else
382
+ case number.to_i % 10
383
+ when 1; "#{number}st"
384
+ when 2; "#{number}nd"
385
+ when 3; "#{number}rd"
386
+ else "#{number}th"
387
+ end
388
+ end
389
+ end
390
+ end
391
+ end
392
+
393
+ # in case caruby/active_support/inflector is required without the rest of active_support
394
+ require 'caruby/active_support/inflections'
395
+ require 'caruby/active_support/core_ext/string/inflections'
396
+ unless String.included_modules.include?(ActiveSupport::CoreExtensions::String::Inflections)
397
+ String.send :include, ActiveSupport::CoreExtensions::String::Inflections
398
+ end