datamapper 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/CHANGELOG +5 -1
  2. data/FAQ +96 -0
  3. data/QUICKLINKS +12 -0
  4. data/README +57 -155
  5. data/environment.rb +61 -43
  6. data/example.rb +30 -12
  7. data/lib/data_mapper.rb +6 -1
  8. data/lib/data_mapper/adapters/abstract_adapter.rb +0 -57
  9. data/lib/data_mapper/adapters/data_object_adapter.rb +203 -97
  10. data/lib/data_mapper/adapters/mysql_adapter.rb +4 -0
  11. data/lib/data_mapper/adapters/postgresql_adapter.rb +7 -1
  12. data/lib/data_mapper/adapters/sql/coersion.rb +3 -2
  13. data/lib/data_mapper/adapters/sql/commands/load_command.rb +29 -10
  14. data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +4 -0
  15. data/lib/data_mapper/adapters/sql/mappings/column.rb +13 -9
  16. data/lib/data_mapper/adapters/sql/mappings/conditions.rb +172 -0
  17. data/lib/data_mapper/adapters/sql/mappings/table.rb +43 -17
  18. data/lib/data_mapper/adapters/sqlite3_adapter.rb +9 -2
  19. data/lib/data_mapper/associations.rb +75 -3
  20. data/lib/data_mapper/associations/belongs_to_association.rb +70 -36
  21. data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +195 -86
  22. data/lib/data_mapper/associations/has_many_association.rb +168 -61
  23. data/lib/data_mapper/associations/has_n_association.rb +23 -3
  24. data/lib/data_mapper/attributes.rb +73 -0
  25. data/lib/data_mapper/auto_migrations.rb +2 -6
  26. data/lib/data_mapper/base.rb +5 -9
  27. data/lib/data_mapper/database.rb +4 -3
  28. data/lib/data_mapper/embedded_value.rb +66 -30
  29. data/lib/data_mapper/identity_map.rb +1 -3
  30. data/lib/data_mapper/is/tree.rb +121 -0
  31. data/lib/data_mapper/migration.rb +155 -0
  32. data/lib/data_mapper/persistence.rb +532 -218
  33. data/lib/data_mapper/property.rb +306 -0
  34. data/lib/data_mapper/query.rb +164 -0
  35. data/lib/data_mapper/support/blank.rb +2 -2
  36. data/lib/data_mapper/support/connection_pool.rb +5 -6
  37. data/lib/data_mapper/support/enumerable.rb +3 -3
  38. data/lib/data_mapper/support/errors.rb +10 -1
  39. data/lib/data_mapper/support/inflector.rb +174 -238
  40. data/lib/data_mapper/support/object.rb +54 -0
  41. data/lib/data_mapper/support/serialization.rb +19 -1
  42. data/lib/data_mapper/support/string.rb +7 -16
  43. data/lib/data_mapper/support/symbol.rb +3 -15
  44. data/lib/data_mapper/support/typed_set.rb +68 -0
  45. data/lib/data_mapper/types/base.rb +44 -0
  46. data/lib/data_mapper/types/string.rb +34 -0
  47. data/lib/data_mapper/validations/number_validator.rb +40 -0
  48. data/lib/data_mapper/validations/string_validator.rb +20 -0
  49. data/lib/data_mapper/validations/validator.rb +13 -0
  50. data/performance.rb +26 -1
  51. data/profile_data_mapper.rb +1 -1
  52. data/rakefile.rb +42 -2
  53. data/spec/acts_as_tree_spec.rb +11 -3
  54. data/spec/adapters/data_object_adapter_spec.rb +31 -0
  55. data/spec/associations/belongs_to_association_spec.rb +98 -0
  56. data/spec/associations/has_and_belongs_to_many_association_spec.rb +377 -0
  57. data/spec/associations/has_many_association_spec.rb +337 -0
  58. data/spec/attributes_spec.rb +23 -1
  59. data/spec/auto_migrations_spec.rb +86 -29
  60. data/spec/callbacks_spec.rb +107 -0
  61. data/spec/column_spec.rb +5 -2
  62. data/spec/count_command_spec.rb +33 -1
  63. data/spec/database_spec.rb +18 -0
  64. data/spec/dependency_spec.rb +4 -2
  65. data/spec/embedded_value_spec.rb +8 -8
  66. data/spec/fixtures/people.yaml +1 -1
  67. data/spec/fixtures/projects.yaml +10 -1
  68. data/spec/fixtures/tasks.yaml +6 -0
  69. data/spec/fixtures/tasks_tasks.yaml +2 -0
  70. data/spec/fixtures/tomatoes.yaml +1 -0
  71. data/spec/is_a_tree_spec.rb +149 -0
  72. data/spec/load_command_spec.rb +71 -9
  73. data/spec/magic_columns_spec.rb +17 -2
  74. data/spec/migration_spec.rb +267 -0
  75. data/spec/models/animal.rb +1 -1
  76. data/spec/models/candidate.rb +8 -0
  77. data/spec/models/career.rb +1 -1
  78. data/spec/models/chain.rb +8 -0
  79. data/spec/models/comment.rb +1 -1
  80. data/spec/models/exhibit.rb +1 -1
  81. data/spec/models/fence.rb +7 -0
  82. data/spec/models/fruit.rb +2 -2
  83. data/spec/models/job.rb +8 -0
  84. data/spec/models/person.rb +2 -3
  85. data/spec/models/post.rb +1 -1
  86. data/spec/models/project.rb +21 -1
  87. data/spec/models/section.rb +1 -1
  88. data/spec/models/serializer.rb +1 -1
  89. data/spec/models/task.rb +9 -0
  90. data/spec/models/tomato.rb +27 -0
  91. data/spec/models/user.rb +8 -2
  92. data/spec/models/zoo.rb +2 -7
  93. data/spec/paranoia_spec.rb +1 -1
  94. data/spec/{base_spec.rb → persistence_spec.rb} +207 -18
  95. data/spec/postgres_spec.rb +48 -6
  96. data/spec/property_spec.rb +90 -9
  97. data/spec/query_spec.rb +71 -5
  98. data/spec/save_command_spec.rb +11 -0
  99. data/spec/spec_helper.rb +14 -11
  100. data/spec/support/blank_spec.rb +8 -0
  101. data/spec/support/inflector_spec.rb +41 -0
  102. data/spec/support/object_spec.rb +9 -0
  103. data/spec/{serialization_spec.rb → support/serialization_spec.rb} +1 -1
  104. data/spec/support/silence_spec.rb +15 -0
  105. data/spec/{support_spec.rb → support/string_spec.rb} +3 -3
  106. data/spec/support/struct_spec.rb +12 -0
  107. data/spec/support/typed_set_spec.rb +66 -0
  108. data/spec/table_spec.rb +3 -3
  109. data/spec/types/string.rb +81 -0
  110. data/spec/validates_uniqueness_of_spec.rb +17 -0
  111. data/spec/validations/number_validator.rb +59 -0
  112. data/spec/validations/string_validator.rb +14 -0
  113. metadata +59 -17
  114. data/do_performance.rb +0 -153
  115. data/lib/data_mapper/support/active_record_impersonation.rb +0 -103
  116. data/lib/data_mapper/support/weak_hash.rb +0 -46
  117. data/spec/active_record_impersonation_spec.rb +0 -129
  118. data/spec/associations_spec.rb +0 -232
  119. data/spec/conditions_spec.rb +0 -49
  120. data/spec/has_many_association_spec.rb +0 -173
  121. data/spec/models/animals_exhibit.rb +0 -8
@@ -4,7 +4,7 @@ class Object
4
4
  end
5
5
  end
6
6
 
7
- class Fixnum
7
+ class Numeric
8
8
  def blank?
9
9
  false
10
10
  end
@@ -24,7 +24,7 @@ end
24
24
 
25
25
  class FalseClass
26
26
  def blank?
27
- false
27
+ true
28
28
  end
29
29
  end
30
30
 
@@ -15,11 +15,15 @@ module DataMapper
15
15
 
16
16
  # The maximum number of connections.
17
17
  attr_reader :max_size
18
+
19
+ # Returns the number of created connections.
20
+ attr_reader :created_count
21
+ alias :size :created_count
18
22
 
19
23
  # The proc used to create a new connection.
20
24
  attr_accessor :connection_proc
21
25
 
22
- attr_reader :available_connections, :allocated, :created_count
26
+ attr_reader :available_connections, :allocated
23
27
 
24
28
  # Constructs a new pool with a maximum size. If a block is supplied, it
25
29
  # is used to create new connections as they are needed.
@@ -41,11 +45,6 @@ module DataMapper
41
45
  @created_count = 0
42
46
  end
43
47
 
44
- # Returns the number of created connections.
45
- def size
46
- @created_count
47
- end
48
-
49
48
  # Assigns a connection to the current thread, yielding the connection
50
49
  # to the supplied block.
51
50
  #
@@ -8,7 +8,7 @@ module DataMapper
8
8
  module Support
9
9
 
10
10
  # Extends Array to include an instance method for grouping objects
11
- module Enumerable
11
+ module EnumerableExtensions
12
12
 
13
13
  # Group a collection of elements into groups within a
14
14
  # Hash. The value returned by the block passed to group_by
@@ -29,7 +29,7 @@ module DataMapper
29
29
  end # module Support
30
30
  end # module DataMapper
31
31
 
32
- # Extend Array with DataMapper::Support::Enumerable
32
+ # Extend Array with DataMapper::Support::EnumerableExtensions
33
33
  class Array #:nodoc:
34
- include DataMapper::Support::Enumerable
34
+ include DataMapper::Support::EnumerableExtensions
35
35
  end
@@ -1,7 +1,16 @@
1
1
  module DataMapper
2
2
 
3
- class InvalidRecord < StandardError; end
3
+ class ValidationError < StandardError; end
4
+
5
+ class ObjectNotFoundError < StandardError; end
4
6
 
5
7
  class MaterializationError < StandardError; end
6
8
 
9
+ end
10
+
11
+ class StandardError
12
+
13
+ def display
14
+ "#{message}\n\t#{backtrace.join("\n\t")}"
15
+ end
7
16
  end
@@ -1,276 +1,212 @@
1
- # This file is copied from the ActiveSupport project, which
1
+ # This file was copied from the ActiveSupport project, which
2
2
  # is a part of the Ruby On Rails web-framework (http://rubyonrails.org).
3
+ # Some methods have been modified or removed.
3
4
 
4
5
  require 'singleton'
5
6
 
6
7
  # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
7
8
  # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
8
9
  # in inflections.rb.
9
- module Inflector
10
- # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
11
- # inflection rules. Examples:
12
- #
13
- # Inflector.inflections do |inflect|
14
- # inflect.plural /^(ox)$/i, '\1\2en'
15
- # inflect.singular /^(ox)en/i, '\1'
16
- #
17
- # inflect.irregular 'octopus', 'octopi'
18
- #
19
- # inflect.uncountable "equipment"
20
- # end
21
- #
22
- # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
23
- # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
24
- # already have been loaded.
25
- class Inflections
26
- include Singleton
27
-
28
- attr_reader :plurals, :singulars, :uncountables
10
+ unless defined?(Inflector)
11
+ module Inflector
12
+ # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
13
+ # inflection rules. Examples:
14
+ #
15
+ # Inflector.inflections do |inflect|
16
+ # inflect.plural /^(ox)$/i, '\1\2en'
17
+ # inflect.singular /^(ox)en/i, '\1'
18
+ #
19
+ # inflect.irregular 'octopus', 'octopi'
20
+ #
21
+ # inflect.uncountable "equipment"
22
+ # end
23
+ #
24
+ # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
25
+ # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
26
+ # already have been loaded.
27
+ class Inflections
28
+ include Singleton
29
29
 
30
- def initialize
31
- @plurals, @singulars, @uncountables = [], [], []
32
- end
30
+ attr_reader :plurals, :singulars, :uncountables
33
31
 
34
- # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
35
- # The replacement should always be a string that may include references to the matched data from the rule.
36
- def plural(rule, replacement)
37
- @plurals.insert(0, [rule, replacement])
38
- end
32
+ def initialize
33
+ @plurals, @singulars, @uncountables = [], [], []
34
+ end
39
35
 
40
- # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
41
- # The replacement should always be a string that may include references to the matched data from the rule.
42
- def singular(rule, replacement)
43
- @singulars.insert(0, [rule, replacement])
44
- end
36
+ # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
37
+ # The replacement should always be a string that may include references to the matched data from the rule.
38
+ def plural(rule, replacement)
39
+ @plurals.insert(0, [rule, replacement])
40
+ end
45
41
 
46
- # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
47
- # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
48
- #
49
- # Examples:
50
- # irregular 'octopus', 'octopi'
51
- # irregular 'person', 'people'
52
- def irregular(singular, plural)
53
- plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
54
- singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
55
- end
42
+ # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
43
+ # The replacement should always be a string that may include references to the matched data from the rule.
44
+ def singular(rule, replacement)
45
+ @singulars.insert(0, [rule, replacement])
46
+ end
56
47
 
57
- # Add uncountable words that shouldn't be attempted inflected.
58
- #
59
- # Examples:
60
- # uncountable "money"
61
- # uncountable "money", "information"
62
- # uncountable %w( money information rice )
63
- def uncountable(*words)
64
- (@uncountables << words).flatten!
65
- end
48
+ # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
49
+ # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
50
+ #
51
+ # Examples:
52
+ # irregular 'octopus', 'octopi'
53
+ # irregular 'person', 'people'
54
+ def irregular(singular, plural)
55
+ plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
56
+ singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
57
+ end
66
58
 
67
- # Clears the loaded inflections within a given scope (default is :all). Give the scope as a symbol of the inflection type,
68
- # the options are: :plurals, :singulars, :uncountables
69
- #
70
- # Examples:
71
- # clear :all
72
- # clear :plurals
73
- def clear(scope = :all)
74
- case scope
75
- when :all
76
- @plurals, @singulars, @uncountables = [], [], []
77
- else
78
- instance_variable_set "@#{scope}", []
59
+ # Add uncountable words that shouldn't be attempted inflected.
60
+ #
61
+ # Examples:
62
+ # uncountable "money"
63
+ # uncountable "money", "information"
64
+ # uncountable %w( money information rice )
65
+ def uncountable(*words)
66
+ (@uncountables << words).flatten!
79
67
  end
80
68
  end
81
- end
82
69
 
83
- extend self
70
+ extend self
84
71
 
85
- def inflections
86
- if block_given?
87
- yield Inflections.instance
88
- else
89
- Inflections.instance
72
+ def inflections
73
+ if block_given?
74
+ yield Inflections.instance
75
+ else
76
+ Inflections.instance
77
+ end
90
78
  end
91
- end
92
79
 
93
- # Returns the plural form of the word in the string.
94
- #
95
- # Examples
96
- # "post".pluralize #=> "posts"
97
- # "octopus".pluralize #=> "octopi"
98
- # "sheep".pluralize #=> "sheep"
99
- # "words".pluralize #=> "words"
100
- # "the blue mailman".pluralize #=> "the blue mailmen"
101
- # "CamelOctopus".pluralize #=> "CamelOctopi"
102
- def pluralize(word)
103
- result = word.to_s.dup
80
+ # Returns the plural form of the word in the string.
81
+ #
82
+ # Examples
83
+ # "post".pluralize #=> "posts"
84
+ # "octopus".pluralize #=> "octopi"
85
+ # "sheep".pluralize #=> "sheep"
86
+ # "words".pluralize #=> "words"
87
+ # "the blue mailman".pluralize #=> "the blue mailmen"
88
+ # "CamelOctopus".pluralize #=> "CamelOctopi"
89
+ def pluralize(word)
90
+ result = word.to_s.dup
104
91
 
105
- if inflections.uncountables.include?(result.downcase)
106
- result
107
- else
108
- inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
109
- result
92
+ if inflections.uncountables.include?(result.downcase)
93
+ result
94
+ else
95
+ inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
96
+ result
97
+ end
110
98
  end
111
- end
112
99
 
113
- # The reverse of pluralize, returns the singular form of a word in a string.
114
- #
115
- # Examples
116
- # "posts".singularize #=> "post"
117
- # "octopi".singularize #=> "octopus"
118
- # "sheep".singluarize #=> "sheep"
119
- # "word".singluarize #=> "word"
120
- # "the blue mailmen".singularize #=> "the blue mailman"
121
- # "CamelOctopi".singularize #=> "CamelOctopus"
122
- def singularize(word)
123
- result = word.to_s.dup
100
+ # The reverse of pluralize, returns the singular form of a word in a string.
101
+ #
102
+ # Examples
103
+ # "posts".singularize #=> "post"
104
+ # "octopi".singularize #=> "octopus"
105
+ # "sheep".singluarize #=> "sheep"
106
+ # "word".singluarize #=> "word"
107
+ # "the blue mailmen".singularize #=> "the blue mailman"
108
+ # "CamelOctopi".singularize #=> "CamelOctopus"
109
+ def singularize(word)
110
+ result = word.to_s.dup
124
111
 
125
- if inflections.uncountables.include?(result.downcase)
126
- result
127
- else
128
- inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
129
- result
112
+ if inflections.uncountables.include?(result.downcase)
113
+ result
114
+ else
115
+ inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
116
+ result
117
+ end
130
118
  end
131
- end
132
119
 
133
- # By default, camelize converts strings to UpperCamelCase. If the argument to camelize
134
- # is set to ":lower" then camelize produces lowerCamelCase.
135
- #
136
- # camelize will also convert '/' to '::' which is useful for converting paths to namespaces
137
- #
138
- # Examples
139
- # "active_record".camelize #=> "ActiveRecord"
140
- # "active_record".camelize(:lower) #=> "activeRecord"
141
- # "active_record/errors".camelize #=> "ActiveRecord::Errors"
142
- # "active_record/errors".camelize(:lower) #=> "activeRecord::Errors"
143
- def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
144
- if first_letter_in_uppercase
120
+ # By default, camelize converts strings to UpperCamelCase.
121
+ #
122
+ # camelize will also convert '/' to '::' which is useful for converting paths to namespaces
123
+ #
124
+ # Examples
125
+ # "active_record".camelize #=> "ActiveRecord"
126
+ # "active_record/errors".camelize #=> "ActiveRecord::Errors"
127
+ def camelize(lower_case_and_underscored_word, *args)
145
128
  lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
146
- else
147
- lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
148
129
  end
149
- end
150
130
 
151
- # Capitalizes all the words and replaces some characters in the string to create
152
- # a nicer looking title. Titleize is meant for creating pretty output. It is not
153
- # used in the Rails internals.
154
- #
155
- # titleize is also aliased as as titlecase
156
- #
157
- # Examples
158
- # "man from the boondocks".titleize #=> "Man From The Boondocks"
159
- # "x-men: the last stand".titleize #=> "X Men: The Last Stand"
160
- def titleize(word)
161
- humanize(underscore(word)).gsub(/\b([a-z])/) { $1.capitalize }
162
- end
163
-
164
- # The reverse of +camelize+. Makes an underscored form from the expression in the string.
165
- #
166
- # Changes '::' to '/' to convert namespaces to paths.
167
- #
168
- # Examples
169
- # "ActiveRecord".underscore #=> "active_record"
170
- # "ActiveRecord::Errors".underscore #=> active_record/errors
171
- def underscore(camel_cased_word)
172
- camel_cased_word.to_s.gsub(/::/, '/').
173
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
174
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
175
- tr("-", "_").
176
- downcase
177
- end
178
-
179
- # Replaces underscores with dashes in the string.
180
- #
181
- # Example
182
- # "puni_puni" #=> "puni-puni"
183
- def dasherize(underscored_word)
184
- underscored_word.gsub(/_/, '-')
185
- end
186
-
187
- # Capitalizes the first word and turns underscores into spaces and strips _id.
188
- # Like titleize, this is meant for creating pretty output.
189
- #
190
- # Examples
191
- # "employee_salary" #=> "Employee salary"
192
- # "author_id" #=> "Author"
193
- def humanize(lower_case_and_underscored_word)
194
- lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
195
- end
196
-
197
- # Removes the module part from the expression in the string
198
- #
199
- # Examples
200
- # "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections"
201
- # "Inflections".demodulize #=> "Inflections"
202
- def demodulize(class_name_in_module)
203
- class_name_in_module.to_s.gsub(/^.*::/, '')
204
- end
131
+ # The reverse of +camelize+. Makes an underscored form from the expression in the string.
132
+ #
133
+ # Changes '::' to '/' to convert namespaces to paths.
134
+ #
135
+ # Examples
136
+ # "ActiveRecord".underscore #=> "active_record"
137
+ # "ActiveRecord::Errors".underscore #=> active_record/errors
138
+ def underscore(camel_cased_word)
139
+ camel_cased_word.to_s.gsub(/::/, '/').
140
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
141
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
142
+ tr("-", "_").
143
+ downcase
144
+ end
205
145
 
206
- # Create the name of a table like Rails does for models to table names. This method
207
- # uses the pluralize method on the last word in the string.
208
- #
209
- # Examples
210
- # "RawScaledScorer".tableize #=> "raw_scaled_scorers"
211
- # "egg_and_ham".tableize #=> "egg_and_hams"
212
- # "fancyCategory".tableize #=> "fancy_categories"
213
- def tableize(class_name)
214
- pluralize(underscore(class_name))
215
- end
146
+ # Capitalizes the first word and turns underscores into spaces and strips _id.
147
+ # Like titleize, this is meant for creating pretty output.
148
+ #
149
+ # Examples
150
+ # "employee_salary" #=> "Employee salary"
151
+ # "author_id" #=> "Author"
152
+ def humanize(lower_case_and_underscored_word)
153
+ lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
154
+ end
216
155
 
217
- # Create a class name from a table name like Rails does for table names to models.
218
- # Note that this returns a string and not a Class. (To convert to an actual class
219
- # follow classify with constantize.)
220
- #
221
- # Examples
222
- # "egg_and_hams".classify #=> "EggAndHam"
223
- # "post".classify #=> "Post"
224
- def classify(table_name)
225
- # strip out any leading schema name
226
- camelize(singularize(table_name.to_s.sub(/.*\./, '')))
227
- end
156
+ # Removes the module part from the expression in the string
157
+ #
158
+ # Examples
159
+ # "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections"
160
+ # "Inflections".demodulize #=> "Inflections"
161
+ def demodulize(class_name_in_module)
162
+ class_name_in_module.to_s.gsub(/^.*::/, '')
163
+ end
228
164
 
229
- # Creates a foreign key name from a class name.
230
- # +separate_class_name_and_id_with_underscore+ sets whether
231
- # the method should put '_' between the name and 'id'.
232
- #
233
- # Examples
234
- # "Message".foreign_key #=> "message_id"
235
- # "Message".foreign_key(false) #=> "messageid"
236
- # "Admin::Post".foreign_key #=> "post_id"
237
- def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
238
- underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
239
- end
165
+ # Create the name of a table like Rails does for models to table names. This method
166
+ # uses the pluralize method on the last word in the string.
167
+ #
168
+ # Examples
169
+ # "RawScaledScorer".tableize #=> "raw_scaled_scorers"
170
+ # "egg_and_ham".tableize #=> "egg_and_hams"
171
+ # "fancyCategory".tableize #=> "fancy_categories"
172
+ def tableize(class_name)
173
+ pluralize(underscore(class_name))
174
+ end
240
175
 
241
- # Constantize tries to find a declared constant with the name specified
242
- # in the string. It raises a NameError when the name is not in CamelCase
243
- # or is not initialized.
244
- #
245
- # Examples
246
- # "Module".constantize #=> Module
247
- # "Class".constantize #=> Class
248
- def constantize(camel_cased_word)
249
- unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
250
- raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
176
+ # Create a class name from a table name like Rails does for table names to models.
177
+ # Note that this returns a string and not a Class. (To convert to an actual class
178
+ # follow classify with constantize.)
179
+ #
180
+ # Examples
181
+ # "egg_and_hams".classify #=> "EggAndHam"
182
+ # "post".classify #=> "Post"
183
+ def classify(table_name)
184
+ # strip out any leading schema name
185
+ camelize(singularize(table_name.to_s.sub(/.*\./, '')))
251
186
  end
252
187
 
253
- Object.module_eval("::#{$1}", __FILE__, __LINE__)
254
- end
188
+ # Creates a foreign key name from a class name.
189
+ #
190
+ # Examples
191
+ # "Message".foreign_key #=> "message_id"
192
+ # "Admin::Post".foreign_key #=> "post_id"
193
+ def foreign_key(class_name, key = "id")
194
+ underscore(demodulize(class_name.to_s)) << "_" << key.to_s
195
+ end
255
196
 
256
- # Ordinalize turns a number into an ordinal string used to denote the
257
- # position in an ordered sequence such as 1st, 2nd, 3rd, 4th.
258
- #
259
- # Examples
260
- # ordinalize(1) # => "1st"
261
- # ordinalize(2) # => "2nd"
262
- # ordinalize(1002) # => "1002nd"
263
- # ordinalize(1003) # => "1003rd"
264
- def ordinalize(number)
265
- if (11..13).include?(number.to_i % 100)
266
- "#{number}th"
267
- else
268
- case number.to_i % 10
269
- when 1: "#{number}st"
270
- when 2: "#{number}nd"
271
- when 3: "#{number}rd"
272
- else "#{number}th"
197
+ # Constantize tries to find a declared constant with the name specified
198
+ # in the string. It raises a NameError when the name is not in CamelCase
199
+ # or is not initialized.
200
+ #
201
+ # Examples
202
+ # "Module".constantize #=> Module
203
+ # "Class".constantize #=> Class
204
+ def constantize(camel_cased_word)
205
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
206
+ raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
273
207
  end
208
+
209
+ Object.module_eval("::#{$1}", __FILE__, __LINE__)
274
210
  end
275
211
  end
276
212
  end
@@ -326,4 +262,4 @@ Inflector.inflections do |inflect|
326
262
  inflect.irregular('move', 'moves')
327
263
 
328
264
  inflect.uncountable(%w(equipment information rice money species series fish sheep))
329
- end
265
+ end