sequel 2.12.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/CHANGELOG +62 -0
  2. data/README.rdoc +3 -3
  3. data/Rakefile +7 -0
  4. data/doc/advanced_associations.rdoc +44 -0
  5. data/doc/release_notes/3.0.0.txt +221 -0
  6. data/lib/sequel/adapters/amalgalite.rb +208 -0
  7. data/lib/sequel/adapters/db2.rb +3 -0
  8. data/lib/sequel/adapters/dbi.rb +9 -0
  9. data/lib/sequel/adapters/do.rb +0 -4
  10. data/lib/sequel/adapters/firebird.rb +16 -18
  11. data/lib/sequel/adapters/informix.rb +5 -3
  12. data/lib/sequel/adapters/jdbc.rb +24 -20
  13. data/lib/sequel/adapters/jdbc/h2.rb +15 -4
  14. data/lib/sequel/adapters/mysql.rb +4 -8
  15. data/lib/sequel/adapters/odbc.rb +0 -4
  16. data/lib/sequel/adapters/oracle.rb +0 -4
  17. data/lib/sequel/adapters/shared/mssql.rb +16 -5
  18. data/lib/sequel/adapters/shared/mysql.rb +87 -86
  19. data/lib/sequel/adapters/shared/oracle.rb +92 -3
  20. data/lib/sequel/adapters/shared/postgres.rb +85 -29
  21. data/lib/sequel/adapters/shared/progress.rb +8 -3
  22. data/lib/sequel/adapters/shared/sqlite.rb +53 -23
  23. data/lib/sequel/adapters/sqlite.rb +4 -7
  24. data/lib/sequel/adapters/utils/unsupported.rb +3 -3
  25. data/lib/sequel/connection_pool.rb +18 -25
  26. data/lib/sequel/core.rb +2 -21
  27. data/lib/sequel/database.rb +60 -44
  28. data/lib/sequel/database/schema_generator.rb +26 -31
  29. data/lib/sequel/database/schema_methods.rb +8 -3
  30. data/lib/sequel/database/schema_sql.rb +114 -28
  31. data/lib/sequel/dataset.rb +14 -41
  32. data/lib/sequel/dataset/convenience.rb +31 -54
  33. data/lib/sequel/dataset/graph.rb +7 -13
  34. data/lib/sequel/dataset/sql.rb +43 -54
  35. data/lib/sequel/extensions/inflector.rb +0 -5
  36. data/lib/sequel/extensions/schema_dumper.rb +238 -0
  37. data/lib/sequel/metaprogramming.rb +0 -20
  38. data/lib/sequel/model.rb +1 -2
  39. data/lib/sequel/model/base.rb +18 -16
  40. data/lib/sequel/model/inflections.rb +6 -9
  41. data/lib/sequel/plugins/caching.rb +0 -6
  42. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  43. data/lib/sequel/sql.rb +2 -0
  44. data/lib/sequel/version.rb +2 -2
  45. data/spec/adapters/firebird_spec.rb +35 -8
  46. data/spec/adapters/mysql_spec.rb +173 -266
  47. data/spec/adapters/oracle_spec.rb +13 -0
  48. data/spec/adapters/postgres_spec.rb +127 -227
  49. data/spec/adapters/sqlite_spec.rb +13 -171
  50. data/spec/core/connection_pool_spec.rb +15 -4
  51. data/spec/core/core_sql_spec.rb +14 -170
  52. data/spec/core/database_spec.rb +50 -132
  53. data/spec/core/dataset_spec.rb +47 -930
  54. data/spec/core/expression_filters_spec.rb +12 -0
  55. data/spec/core/schema_generator_spec.rb +37 -45
  56. data/spec/core/schema_spec.rb +26 -16
  57. data/spec/core/spec_helper.rb +0 -25
  58. data/spec/extensions/inflector_spec.rb +0 -3
  59. data/spec/extensions/schema_dumper_spec.rb +292 -0
  60. data/spec/extensions/serialization_spec.rb +9 -0
  61. data/spec/extensions/single_table_inheritance_spec.rb +6 -1
  62. data/spec/extensions/spec_helper.rb +1 -3
  63. data/spec/extensions/validation_helpers_spec.rb +4 -4
  64. data/spec/integration/database_test.rb +18 -0
  65. data/spec/integration/dataset_test.rb +112 -1
  66. data/spec/integration/eager_loader_test.rb +70 -9
  67. data/spec/integration/prepared_statement_test.rb +2 -2
  68. data/spec/integration/schema_test.rb +76 -27
  69. data/spec/integration/spec_helper.rb +0 -14
  70. data/spec/integration/transaction_test.rb +27 -0
  71. data/spec/model/associations_spec.rb +0 -36
  72. data/spec/model/base_spec.rb +18 -123
  73. data/spec/model/hooks_spec.rb +2 -235
  74. data/spec/model/inflector_spec.rb +15 -115
  75. data/spec/model/model_spec.rb +0 -120
  76. data/spec/model/plugins_spec.rb +0 -70
  77. data/spec/model/record_spec.rb +35 -93
  78. data/spec/model/spec_helper.rb +0 -27
  79. data/spec/model/validations_spec.rb +0 -931
  80. metadata +9 -14
  81. data/lib/sequel/deprecated.rb +0 -593
  82. data/lib/sequel/deprecated_migration.rb +0 -91
  83. data/lib/sequel/model/deprecated.rb +0 -204
  84. data/lib/sequel/model/deprecated_hooks.rb +0 -103
  85. data/lib/sequel/model/deprecated_inflector.rb +0 -335
  86. data/lib/sequel/model/deprecated_validations.rb +0 -388
  87. data/spec/core/core_ext_spec.rb +0 -156
  88. data/spec/core/migration_spec.rb +0 -263
  89. data/spec/core/pretty_table_spec.rb +0 -58
  90. data/spec/model/caching_spec.rb +0 -217
  91. data/spec/model/schema_spec.rb +0 -92
@@ -1,91 +0,0 @@
1
- module Sequel
2
- class Migration
3
- def initialize(db)
4
- Deprecation.deprecate('Sequel::Migration', "require 'sequel/extensions/migration' first")
5
- require 'sequel/extensions/migration'
6
- @db = db
7
- end
8
-
9
- def self.apply(db, direction)
10
- Deprecation.deprecate('Sequel::Migration', "require 'sequel/extensions/migration' first")
11
- require 'sequel/extensions/migration'
12
- apply(db, direction)
13
- end
14
-
15
- def self.descendants
16
- Deprecation.deprecate('Sequel::Migration', "require 'sequel/extensions/migration' first")
17
- require 'sequel/extensions/migration'
18
- @descendants ||= []
19
- end
20
-
21
- def self.inherited(base)
22
- Deprecation.deprecate('Sequel::Migration', "require 'sequel/extensions/migration' first")
23
- require 'sequel/extensions/migration'
24
- descendants << base
25
- end
26
-
27
- def down
28
- Deprecation.deprecate('Sequel::Migration', "require 'sequel/extensions/migration' first")
29
- require 'sequel/extensions/migration'
30
- end
31
-
32
- def method_missing(method_sym, *args, &block)
33
- Deprecation.deprecate('Sequel::Migration', "require 'sequel/extensions/migration' first")
34
- require 'sequel/extensions/migration'
35
- @db.send(method_sym, *args, &block)
36
- end
37
-
38
- def up
39
- Deprecation.deprecate('Sequel::Migration', "require 'sequel/extensions/migration' first")
40
- require 'sequel/extensions/migration'
41
- end
42
- end
43
-
44
- module Migrator
45
- def self.apply(db, directory, target = nil, current = nil)
46
- Deprecation.deprecate('Sequel::Migrator', "require 'sequel/extensions/migration' first")
47
- require 'sequel/extensions/migration'
48
- apply(db, directory, target, current)
49
- end
50
-
51
- def self.get_current_migration_version(db)
52
- Deprecation.deprecate('Sequel::Migrator', "require 'sequel/extensions/migration' first")
53
- require 'sequel/extensions/migration'
54
- r = schema_info_dataset(db).first
55
- r ? r[:version] : 0
56
- end
57
-
58
- def self.latest_migration_version(directory)
59
- Deprecation.deprecate('Sequel::Migrator', "require 'sequel/extensions/migration' first")
60
- require 'sequel/extensions/migration'
61
- l = migration_files(directory).last
62
- l ? File.basename(l).to_i : nil
63
- end
64
-
65
- def self.migration_classes(directory, target, current, direction)
66
- Deprecation.deprecate('Sequel::Migrator', "require 'sequel/extensions/migration' first")
67
- require 'sequel/extensions/migration'
68
- migration_classes(directory, target, current, direction)
69
- end
70
-
71
- def self.migration_files(directory, range = nil)
72
- Deprecation.deprecate('Sequel::Migrator', "require 'sequel/extensions/migration' first")
73
- require 'sequel/extensions/migration'
74
- migration_files(directory, range)
75
- end
76
-
77
- def self.schema_info_dataset(db)
78
- Deprecation.deprecate('Sequel::Migrator', "require 'sequel/extensions/migration' first")
79
- require 'sequel/extensions/migration'
80
- db.create_table(:schema_info) {integer :version} unless db.table_exists?(:schema_info)
81
- db[:schema_info]
82
- end
83
-
84
- def self.set_current_migration_version(db, version)
85
- Deprecation.deprecate('Sequel::Migrator', "require 'sequel/extensions/migration' first")
86
- require 'sequel/extensions/migration'
87
- dataset = schema_info_dataset(db)
88
- dataset.send(dataset.first ? :update : :<<, :version => version)
89
- end
90
- end
91
- end
@@ -1,204 +0,0 @@
1
- Sequel.require %w'deprecated_hooks deprecated_validations deprecated_inflector', 'model'
2
-
3
- module Sequel
4
- class Model
5
- module Validation
6
- Errors = Model::Errors
7
- end
8
- module ClassMethods
9
- {:size=>:count, :uniq=>:distinct}.each do |o, n|
10
- class_eval "def #{o}(*args, &block); Deprecation.deprecate('Sequel::Model.#{o}', 'Use Sequel::Model.dataset.#{n}'); dataset.#{n}(*args, &block); end"
11
- end
12
-
13
- def is(*args, &block)
14
- Deprecation.deprecate('Sequel::Model.is', 'Use Sequel::Model.plugin')
15
- plugin(*args, &block)
16
- end
17
-
18
- def is_a(*args, &block)
19
- Deprecation.deprecate('Sequel::Model.is_a', 'Use Sequel::Model.plugin')
20
- plugin(*args, &block)
21
- end
22
-
23
- def delete_all
24
- Deprecation.deprecate('Sequel::Model.delete_all', 'Use Sequel::Model.delete')
25
- dataset.delete
26
- end
27
-
28
- def destroy_all
29
- Deprecation.deprecate('Sequel::Model.destroy_all', 'Use Sequel::Model.destroy')
30
- dataset.destroy
31
- end
32
-
33
- def str_columns
34
- Deprecation.deprecate('Sequel::Model.str_columns', 'Use model.columns.map{|x| x.to_s}')
35
- @str_columns ||= columns.map{|c| c.to_s.freeze}
36
- end
37
-
38
- def set_sti_key(key)
39
- Deprecation.deprecate('Sequel::Model.set_sti_key', 'Use Model.plugin(:single_table_inheritance, key)')
40
- plugin :single_table_inheritance, key
41
- end
42
-
43
- def sti_key
44
- Deprecation.deprecate('Sequel::Model.sti_key', 'Use Model.plugin(:single_table_inheritance, key) first')
45
- @sti_key
46
- end
47
-
48
- def sti_dataset
49
- Deprecation.deprecate('Sequel::Model.sti_dataset', 'Use Model.plugin(:single_table_inheritance, key) first')
50
- @sti_dataset
51
- end
52
-
53
- def set_cache_ttl(ttl)
54
- Deprecation.deprecate('Sequel::Model.set_cache_ttl', 'Use Model.plugin(:caching, store, opts) first')
55
- @cache_ttl = ttl
56
- end
57
-
58
- def set_cache(store, opts = {})
59
- Deprecation.deprecate('Sequel::Model.set_cache', 'Use Model.plugin(:caching, store, opts)')
60
- plugin :caching, store, opts
61
- end
62
-
63
- # Creates table, using the column information from set_schema.
64
- def create_table
65
- Deprecation.deprecate('Sequel::Model.create_table', 'Use Model.plugin(:schema) first')
66
- db.create_table(table_name, :generator=>@schema)
67
- @db_schema = get_db_schema(true)
68
- columns
69
- end
70
-
71
- # Drops the table if it exists and then runs create_table. Should probably
72
- # not be used except in testing.
73
- def create_table!
74
- Deprecation.deprecate('Sequel::Model.create_table!', 'Use Model.plugin(:schema) first')
75
- drop_table rescue nil
76
- create_table
77
- end
78
-
79
- # Drops table.
80
- def drop_table
81
- Deprecation.deprecate('Sequel::Model.drop_table', 'Use Model.plugin(:schema) first')
82
- db.drop_table(table_name)
83
- end
84
-
85
- # Returns table schema created with set_schema for direct descendant of Model.
86
- # Does not retreive schema information from the database, see db_schema if you
87
- # want that.
88
- def schema
89
- Deprecation.deprecate('Sequel::Model.schema', 'Use Model.plugin(:schema) first')
90
- @schema || (superclass.schema unless superclass == Model)
91
- end
92
-
93
- # Defines a table schema (see Schema::Generator for more information).
94
- #
95
- # This is only needed if you want to use the create_table/create_table! methods.
96
- # Will also set the dataset if you provide a name, as well as setting
97
- # the primary key if you defined one in the passed block.
98
- #
99
- # In general, it is a better idea to use migrations for production code, as
100
- # migrations allow changes to existing schema. set_schema is mostly useful for
101
- # test code or simple examples.
102
- def set_schema(name = nil, &block)
103
- Deprecation.deprecate('Sequel::Model.set_schema', 'Use Model.plugin(:schema) first')
104
- set_dataset(db[name]) if name
105
- @schema = Sequel::Schema::Generator.new(db, &block)
106
- set_primary_key(@schema.primary_key_name) if @schema.primary_key_name
107
- end
108
-
109
- # Returns true if table exists, false otherwise.
110
- def table_exists?
111
- Deprecation.deprecate('Sequel::Model.table_exists?', 'Use Model.plugin(:schema) first')
112
- db.table_exists?(table_name)
113
- end
114
-
115
- def serialize(*columns)
116
- Deprecation.deprecate('Sequel::Model.serialize', 'A implementation that doesn\'t use dataset transforms can be added via plugin(:serialization, (:marshal||:yaml), column1, column2)')
117
- format = extract_options!(columns)[:format] || :yaml
118
- @transform = columns.inject({}) do |m, c|
119
- m[c] = format
120
- m
121
- end
122
- @dataset.transform(@transform) if @dataset
123
- end
124
-
125
- def serialized?(column)
126
- @transform ? @transform.include?(column) : false
127
- end
128
- end
129
-
130
- module InstanceMethods
131
- def dataset
132
- Deprecation.deprecate('Sequel::Model#dataset', 'Use model_object.model.dataset')
133
- model.dataset
134
- end
135
-
136
- def save!(*args)
137
- Deprecation.deprecate('Sequel::Model#save!', 'Use model_object.save(..., :validate=>false)')
138
- opts = args.last.is_a?(Hash) ? args.pop : {}
139
- args.push(opts.merge(:validate=>false))
140
- save(*args)
141
- end
142
-
143
- def str_columns
144
- Deprecation.deprecate('Sequel::Model#str_columns', 'Use model_object.columns.map{|x| x.to_s}')
145
- model.str_columns
146
- end
147
-
148
- def set_with_params(hash)
149
- Deprecation.deprecate('Sequel::Model#set_with_params', 'Use Sequel::Model#set')
150
- set_restricted(hash, nil, nil)
151
- end
152
-
153
- def update_with_params(hash)
154
- Deprecation.deprecate('Sequel::Model#update_with_params', 'Use Sequel::Model#update')
155
- update_restricted(hash, nil, nil)
156
- end
157
-
158
- def set_values(values)
159
- Deprecation.deprecate('Sequel::Model#set_values', 'Use Sequel::Model#set')
160
- s = str_columns
161
- vals = values.inject({}) do |m, kv|
162
- k, v = kv
163
- k = case k
164
- when Symbol
165
- k
166
- when String
167
- raise(Error, "all string keys must be a valid columns") unless s.include?(k)
168
- k.to_sym
169
- else
170
- raise(Error, "Only symbols and strings allows as keys")
171
- end
172
- m[k] = v
173
- m
174
- end
175
- vals.each {|k, v| @values[k] = v}
176
- vals
177
- end
178
-
179
- def update_values(values)
180
- Deprecation.deprecate('Sequel::Model#update_values', 'Use Sequel::Model#update or model_object.this.update')
181
- this.update(set_values(values))
182
- end
183
- end
184
-
185
- if defined?(Associations::ClassMethods)
186
- module Associations::ClassMethods
187
- def belongs_to(*args, &block)
188
- Deprecation.deprecate('Sequel::Model.belongs_to', 'Use Sequel::Model.many_to_one')
189
- many_to_one(*args, &block)
190
- end
191
-
192
- def has_many(*args, &block)
193
- Deprecation.deprecate('Sequel::Model.has_many', 'Use Sequel::Model.one_to_many')
194
- one_to_many(*args, &block)
195
- end
196
-
197
- def has_and_belongs_to_many(*args, &block)
198
- Deprecation.deprecate('Sequel::Model.has_and_belongs_to_many', 'Use Sequel::Model.many_to_many')
199
- many_to_many(*args, &block)
200
- end
201
- end
202
- end
203
- end
204
- end
@@ -1,103 +0,0 @@
1
- module Sequel
2
- module Plugins
3
- module DeprecatedHookClassMethods
4
- def self.apply(model)
5
- hooks = model.instance_variable_set(:@hooks, {})
6
- Model::HOOKS.each{|h| hooks[h] = []}
7
- end
8
-
9
- module ClassMethods
10
- Model::HOOKS.each{|h| class_eval("def #{h}(method = nil, &block); Deprecation.deprecate('Sequel::Model.#{h}', 'Use Model.plugin :hook_class_methods'); add_hook(:#{h}, method, &block) end", __FILE__, __LINE__)}
11
-
12
- # This adds a new hook type. It will define both a class
13
- # method that you can use to add hooks, as well as an instance method
14
- # that you can use to call all hooks of that type. The class method
15
- # can be called with a symbol or a block or both. If a block is given and
16
- # and symbol is not, it adds the hook block to the hook type. If a block
17
- # and symbol are both given, it replaces the hook block associated with
18
- # that symbol for a given hook type, or adds it if there is no hook block
19
- # with that symbol for that hook type. If no block is given, it assumes
20
- # the symbol specifies an instance method to call and adds it to the hook
21
- # type.
22
- #
23
- # If any hook block returns false, the instance method will return false
24
- # immediately without running the rest of the hooks of that type.
25
- #
26
- # It is recommended that you always provide a symbol to this method,
27
- # for descriptive purposes. It's only necessary to do so when you
28
- # are using a system that reloads code.
29
- #
30
- # Example of usage:
31
- #
32
- # class MyModel
33
- # define_hook :before_move_to
34
- # before_move_to(:check_move_allowed){|o| o.allow_move?}
35
- # def move_to(there)
36
- # return if before_move_to == false
37
- # # move MyModel object to there
38
- # end
39
- # end
40
- def add_hook_type(*hooks)
41
- Deprecation.deprecate('Sequel::Model.add_hook_type', 'Use Model.plugin :hook_class_methods')
42
- hooks.each do |hook|
43
- @hooks[hook] = []
44
- instance_eval("def #{hook}(method = nil, &block); add_hook(:#{hook}, method, &block) end", __FILE__, __LINE__)
45
- class_eval("def #{hook}; run_hooks(:#{hook}); end", __FILE__, __LINE__)
46
- end
47
- end
48
-
49
- # Returns true if there are any hook blocks for the given hook.
50
- def has_hooks?(hook)
51
- !@hooks[hook].empty?
52
- end
53
-
54
- # Yield every block related to the given hook.
55
- def hook_blocks(hook)
56
- @hooks[hook].each{|k,v| yield v}
57
- end
58
-
59
- def inherited(subclass)
60
- super
61
- hooks = subclass.instance_variable_set(:@hooks, {})
62
- instance_variable_get(:@hooks).each{|k,v| hooks[k] = v.dup}
63
- end
64
-
65
- private
66
-
67
- # Add a hook block to the list of hook methods.
68
- # If a non-nil tag is given and it already is in the list of hooks,
69
- # replace it with the new block.
70
- def add_hook(hook, tag, &block)
71
- unless block
72
- (raise Error, 'No hook method specified') unless tag
73
- block = proc {send tag}
74
- end
75
- h = @hooks[hook]
76
- if tag && (old = h.find{|x| x[0] == tag})
77
- old[1] = block
78
- else
79
- if hook.to_s =~ /^before/
80
- h.unshift([tag,block])
81
- else
82
- h << [tag, block]
83
- end
84
- end
85
- end
86
- end
87
-
88
- module InstanceMethods
89
- Model::HOOKS.each{|h| class_eval("def #{h}; run_hooks(:#{h}); end", __FILE__, __LINE__)}
90
-
91
- private
92
-
93
- # Runs all hook blocks of given hook type on this object.
94
- # Stops running hook blocks and returns false if any hook block returns false.
95
- def run_hooks(hook)
96
- model.hook_blocks(hook){|block| return false if instance_eval(&block) == false}
97
- end
98
- end
99
- end
100
- end
101
-
102
- Model.plugin :deprecated_hook_class_methods
103
- end
@@ -1,335 +0,0 @@
1
- # Add inflection methods to String, which allows the easy transformation of
2
- # words from singular to plural,class names to table names, modularized class
3
- # names to ones without, and class names to foreign keys.
4
-
5
- class String
6
- # This module acts as a singleton returned/yielded by String.inflections,
7
- # which is used to override or specify additional inflection rules. Examples:
8
- #
9
- # String.inflections do |inflect|
10
- # inflect.plural /^(ox)$/i, '\1\2en'
11
- # inflect.singular /^(ox)en/i, '\1'
12
- #
13
- # inflect.irregular 'octopus', 'octopi'
14
- #
15
- # inflect.uncountable "equipment"
16
- # end
17
- #
18
- # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
19
- # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
20
- # already have been loaded.
21
- module Inflections
22
- @plurals, @singulars, @uncountables = [], [], []
23
-
24
- class << self
25
- attr_reader :plurals, :singulars, :uncountables
26
- end
27
-
28
- # Clears the loaded inflections within a given scope (default is :all). Give the scope as a symbol of the inflection type,
29
- # the options are: :plurals, :singulars, :uncountables
30
- #
31
- # Examples:
32
- # clear :all
33
- # clear :plurals
34
- def self.clear(scope = :all)
35
- Sequel::Deprecation.deprecate('String::Inflections.clear', 'require "sequel/extensions/inflector" first')
36
- Sequel::Inflections.clear(scope)
37
- case scope
38
- when :all
39
- @plurals, @singulars, @uncountables = [], [], []
40
- else
41
- instance_variable_set("@#{scope}", [])
42
- end
43
- end
44
-
45
- # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
46
- # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
47
- #
48
- # Examples:
49
- # irregular 'octopus', 'octopi'
50
- # irregular 'person', 'people'
51
- def self.irregular(singular, plural)
52
- Sequel::Deprecation.deprecate('String::Inflections.irregular', 'require "sequel/extensions/inflector" first')
53
- Sequel::Inflections.irregular(singular, plural)
54
- plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
55
- singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
56
- end
57
-
58
- # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
59
- # The replacement should always be a string that may include references to the matched data from the rule.
60
- #
61
- # Example:
62
- # plural(/(x|ch|ss|sh)$/i, '\1es')
63
- def self.plural(rule, replacement)
64
- Sequel::Deprecation.deprecate('String::Inflections.plural', 'require "sequel/extensions/inflector" first')
65
- Sequel::Inflections.plural(rule, replacement)
66
- @plurals.insert(0, [rule, replacement])
67
- end
68
-
69
- # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
70
- # The replacement should always be a string that may include references to the matched data from the rule.
71
- #
72
- # Example:
73
- # singular(/([^aeiouy]|qu)ies$/i, '\1y')
74
- def self.singular(rule, replacement)
75
- Sequel::Deprecation.deprecate('String::Inflections.singular', 'require "sequel/extensions/inflector" first')
76
- Sequel::Inflections.singular(rule, replacement)
77
- @singulars.insert(0, [rule, replacement])
78
- end
79
-
80
- # Add uncountable words that shouldn't be attempted inflected.
81
- #
82
- # Examples:
83
- # uncountable "money"
84
- # uncountable "money", "information"
85
- # uncountable %w( money information rice )
86
- def self.uncountable(*words)
87
- Sequel::Deprecation.deprecate('String::Inflections.uncountable', 'require "sequel/extensions/inflector" first')
88
- Sequel::Inflections.uncountable(*words)
89
- (@uncountables << words).flatten!
90
- end
91
-
92
- output = Sequel::Deprecation.output
93
- Sequel::Deprecation.output = nil
94
- # Setup the default inflections
95
- plural(/$/, 's')
96
- plural(/s$/i, 's')
97
- plural(/(ax|test)is$/i, '\1es')
98
- plural(/(octop|vir)us$/i, '\1i')
99
- plural(/(alias|status)$/i, '\1es')
100
- plural(/(bu)s$/i, '\1ses')
101
- plural(/(buffal|tomat)o$/i, '\1oes')
102
- plural(/([ti])um$/i, '\1a')
103
- plural(/sis$/i, 'ses')
104
- plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
105
- plural(/(hive)$/i, '\1s')
106
- plural(/([^aeiouy]|qu)y$/i, '\1ies')
107
- plural(/(x|ch|ss|sh)$/i, '\1es')
108
- plural(/(matr|vert|ind)ix|ex$/i, '\1ices')
109
- plural(/([m|l])ouse$/i, '\1ice')
110
- plural(/^(ox)$/i, '\1en')
111
- plural(/(quiz)$/i, '\1zes')
112
-
113
- singular(/s$/i, '')
114
- singular(/(n)ews$/i, '\1ews')
115
- singular(/([ti])a$/i, '\1um')
116
- singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis')
117
- singular(/(^analy)ses$/i, '\1sis')
118
- singular(/([^f])ves$/i, '\1fe')
119
- singular(/(hive)s$/i, '\1')
120
- singular(/(tive)s$/i, '\1')
121
- singular(/([lr])ves$/i, '\1f')
122
- singular(/([^aeiouy]|qu)ies$/i, '\1y')
123
- singular(/(s)eries$/i, '\1eries')
124
- singular(/(m)ovies$/i, '\1ovie')
125
- singular(/(x|ch|ss|sh)es$/i, '\1')
126
- singular(/([m|l])ice$/i, '\1ouse')
127
- singular(/(bus)es$/i, '\1')
128
- singular(/(o)es$/i, '\1')
129
- singular(/(shoe)s$/i, '\1')
130
- singular(/(cris|ax|test)es$/i, '\1is')
131
- singular(/(octop|vir)i$/i, '\1us')
132
- singular(/(alias|status)es$/i, '\1')
133
- singular(/^(ox)en/i, '\1')
134
- singular(/(vert|ind)ices$/i, '\1ex')
135
- singular(/(matr)ices$/i, '\1ix')
136
- singular(/(quiz)zes$/i, '\1')
137
-
138
- irregular('person', 'people')
139
- irregular('man', 'men')
140
- irregular('child', 'children')
141
- irregular('sex', 'sexes')
142
- irregular('move', 'moves')
143
-
144
- uncountable(%w(equipment information rice money species series fish sheep))
145
- Sequel::Deprecation.output = output
146
- end
147
-
148
- # Yield the Inflections module if a block is given, and return
149
- # the Inflections module.
150
- def self.inflections
151
- Sequel::Deprecation.deprecate('String.inflections', 'require "sequel/extensions/inflector" first')
152
- yield Inflections if block_given?
153
- Inflections
154
- end
155
-
156
- include(Module.new do
157
- unless String.method_defined?(:camelize)
158
- # By default, camelize converts the string to UpperCamelCase. If the argument to camelize
159
- # is set to :lower then camelize produces lowerCamelCase.
160
- #
161
- # camelize will also convert '/' to '::' which is useful for converting paths to namespaces
162
- #
163
- # Examples
164
- # "active_record".camelize #=> "ActiveRecord"
165
- # "active_record".camelize(:lower) #=> "activeRecord"
166
- # "active_record/errors".camelize #=> "ActiveRecord::Errors"
167
- # "active_record/errors".camelize(:lower) #=> "activeRecord::Errors"
168
- def camelize(first_letter_in_uppercase = :upper)
169
- Sequel::Deprecation.deprecate('String#camelize', 'require "sequel/extensions/inflector" first')
170
- s = gsub(/\/(.?)/){|x| "::#{x[-1..-1].upcase unless x == '/'}"}.gsub(/(^|_)(.)/){|x| x[-1..-1].upcase}
171
- s[0...1] = s[0...1].downcase unless first_letter_in_uppercase == :upper
172
- s
173
- end
174
- alias camelcase camelize
175
- end
176
-
177
- unless String.method_defined?(:camelize)
178
- # Singularizes and camelizes the string. Also strips out all characters preceding
179
- # and including a period (".").
180
- #
181
- # Examples
182
- # "egg_and_hams".classify #=> "EggAndHam"
183
- # "post".classify #=> "Post"
184
- # "schema.post".classify #=> "Post"
185
- def classify
186
- Sequel::Deprecation.deprecate('String#classify', 'require "sequel/extensions/inflector" first')
187
- sub(/.*\./, '').singularize.camelize
188
- end
189
- end
190
-
191
- unless String.method_defined?(:camelize)
192
- # Constantize tries to find a declared constant with the name specified
193
- # in the string. It raises a NameError when the name is not in CamelCase
194
- # or is not initialized.
195
- #
196
- # Examples
197
- # "Module".constantize #=> Module
198
- # "Class".constantize #=> Class
199
- def constantize
200
- Sequel::Deprecation.deprecate('String#constantize', 'require "sequel/extensions/inflector" first')
201
- raise(NameError, "#{inspect} is not a valid constant name!") unless m = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.match(self)
202
- Object.module_eval("::#{m[1]}", __FILE__, __LINE__)
203
- end
204
- end
205
-
206
- unless String.method_defined?(:camelize)
207
- # Replaces underscores with dashes in the string.
208
- #
209
- # Example
210
- # "puni_puni".dasherize #=> "puni-puni"
211
- def dasherize
212
- Sequel::Deprecation.deprecate('String#dasherize', 'require "sequel/extensions/inflector" first')
213
- gsub(/_/, '-')
214
- end
215
- end
216
-
217
- unless String.method_defined?(:camelize)
218
- # Removes the module part from the expression in the string
219
- #
220
- # Examples
221
- # "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections"
222
- # "Inflections".demodulize #=> "Inflections"
223
- def demodulize
224
- Sequel::Deprecation.deprecate('String#demodulize', 'require "sequel/extensions/inflector" first')
225
- gsub(/^.*::/, '')
226
- end
227
- end
228
-
229
- unless String.method_defined?(:camelize)
230
- # Creates a foreign key name from a class name.
231
- # +use_underscore+ sets whether 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(use_underscore = true)
238
- Sequel::Deprecation.deprecate('String#foreign_key', 'require "sequel/extensions/inflector" first')
239
- "#{demodulize.underscore}#{'_' if use_underscore}id"
240
- end
241
- end
242
-
243
- unless String.method_defined?(:camelize)
244
- # Capitalizes the first word and turns underscores into spaces and strips _id.
245
- # Like titleize, this is meant for creating pretty output.
246
- #
247
- # Examples
248
- # "employee_salary" #=> "Employee salary"
249
- # "author_id" #=> "Author"
250
- def humanize
251
- Sequel::Deprecation.deprecate('String#humanize', 'require "sequel/extensions/inflector" first')
252
- gsub(/_id$/, "").gsub(/_/, " ").capitalize
253
- end
254
- end
255
-
256
- unless String.method_defined?(:camelize)
257
- # Returns the plural form of the word in the string.
258
- #
259
- # Examples
260
- # "post".pluralize #=> "posts"
261
- # "octopus".pluralize #=> "octopi"
262
- # "sheep".pluralize #=> "sheep"
263
- # "words".pluralize #=> "words"
264
- # "the blue mailman".pluralize #=> "the blue mailmen"
265
- # "CamelOctopus".pluralize #=> "CamelOctopi"
266
- def pluralize
267
- Sequel::Deprecation.deprecate('String#pluralize', 'require "sequel/extensions/inflector" first')
268
- result = dup
269
- Inflections.plurals.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(downcase)
270
- result
271
- end
272
- end
273
-
274
- unless String.method_defined?(:camelize)
275
- # The reverse of pluralize, returns the singular form of a word in a string.
276
- #
277
- # Examples
278
- # "posts".singularize #=> "post"
279
- # "octopi".singularize #=> "octopus"
280
- # "sheep".singluarize #=> "sheep"
281
- # "word".singluarize #=> "word"
282
- # "the blue mailmen".singularize #=> "the blue mailman"
283
- # "CamelOctopi".singularize #=> "CamelOctopus"
284
- def singularize
285
- Sequel::Deprecation.deprecate('String#singularize', 'require "sequel/extensions/inflector" first')
286
- result = dup
287
- Inflections.singulars.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(downcase)
288
- result
289
- end
290
- end
291
-
292
- unless String.method_defined?(:camelize)
293
- # Underscores and pluralizes the string.
294
- #
295
- # Examples
296
- # "RawScaledScorer".tableize #=> "raw_scaled_scorers"
297
- # "egg_and_ham".tableize #=> "egg_and_hams"
298
- # "fancyCategory".tableize #=> "fancy_categories"
299
- def tableize
300
- Sequel::Deprecation.deprecate('String#tableize', 'require "sequel/extensions/inflector" first')
301
- underscore.pluralize
302
- end
303
- end
304
-
305
- unless String.method_defined?(:camelize)
306
- # Capitalizes all the words and replaces some characters in the string to create
307
- # a nicer looking title. Titleize is meant for creating pretty output.
308
- #
309
- # titleize is also aliased as as titlecase
310
- #
311
- # Examples
312
- # "man from the boondocks".titleize #=> "Man From The Boondocks"
313
- # "x-men: the last stand".titleize #=> "X Men: The Last Stand"
314
- def titleize
315
- Sequel::Deprecation.deprecate('String#titleize', 'require "sequel/extensions/inflector" first')
316
- underscore.humanize.gsub(/\b([a-z])/){|x| x[-1..-1].upcase}
317
- end
318
- alias titlecase titleize
319
- end
320
-
321
- unless String.method_defined?(:camelize)
322
- # The reverse of camelize. Makes an underscored form from the expression in the string.
323
- # Also changes '::' to '/' to convert namespaces to paths.
324
- #
325
- # Examples
326
- # "ActiveRecord".underscore #=> "active_record"
327
- # "ActiveRecord::Errors".underscore #=> active_record/errors
328
- def underscore
329
- Sequel::Deprecation.deprecate('String#underscore', 'require "sequel/extensions/inflector" first')
330
- gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
331
- gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
332
- end
333
- end
334
- end)
335
- end