sequel 2.11.0 → 2.12.0

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 (162) hide show
  1. data/CHANGELOG +168 -0
  2. data/README.rdoc +77 -95
  3. data/Rakefile +100 -80
  4. data/bin/sequel +2 -1
  5. data/doc/advanced_associations.rdoc +23 -32
  6. data/doc/cheat_sheet.rdoc +23 -40
  7. data/doc/dataset_filtering.rdoc +6 -6
  8. data/doc/prepared_statements.rdoc +22 -22
  9. data/doc/release_notes/2.12.0.txt +534 -0
  10. data/doc/schema.rdoc +3 -1
  11. data/doc/sharding.rdoc +8 -8
  12. data/doc/virtual_rows.rdoc +65 -0
  13. data/lib/sequel.rb +1 -1
  14. data/lib/{sequel_core → sequel}/adapters/ado.rb +3 -3
  15. data/lib/{sequel_core → sequel}/adapters/db2.rb +0 -0
  16. data/lib/{sequel_core → sequel}/adapters/dbi.rb +1 -1
  17. data/lib/{sequel_core → sequel}/adapters/do.rb +9 -5
  18. data/lib/{sequel_core → sequel}/adapters/do/mysql.rb +1 -1
  19. data/lib/{sequel_core → sequel}/adapters/do/postgres.rb +1 -1
  20. data/lib/{sequel_core → sequel}/adapters/do/sqlite.rb +1 -1
  21. data/lib/{sequel_core → sequel}/adapters/firebird.rb +84 -80
  22. data/lib/{sequel_core → sequel}/adapters/informix.rb +1 -1
  23. data/lib/{sequel_core → sequel}/adapters/jdbc.rb +21 -14
  24. data/lib/{sequel_core → sequel}/adapters/jdbc/h2.rb +14 -13
  25. data/lib/{sequel_core → sequel}/adapters/jdbc/mysql.rb +1 -1
  26. data/lib/{sequel_core → sequel}/adapters/jdbc/oracle.rb +1 -1
  27. data/lib/{sequel_core → sequel}/adapters/jdbc/postgresql.rb +1 -1
  28. data/lib/{sequel_core → sequel}/adapters/jdbc/sqlite.rb +1 -1
  29. data/lib/{sequel_core → sequel}/adapters/mysql.rb +60 -39
  30. data/lib/{sequel_core → sequel}/adapters/odbc.rb +8 -4
  31. data/lib/{sequel_core → sequel}/adapters/openbase.rb +0 -0
  32. data/lib/{sequel_core → sequel}/adapters/oracle.rb +38 -7
  33. data/lib/{sequel_core → sequel}/adapters/postgres.rb +24 -24
  34. data/lib/{sequel_core → sequel}/adapters/shared/mssql.rb +5 -5
  35. data/lib/{sequel_core → sequel}/adapters/shared/mysql.rb +126 -71
  36. data/lib/{sequel_core → sequel}/adapters/shared/oracle.rb +7 -10
  37. data/lib/{sequel_core → sequel}/adapters/shared/postgres.rb +159 -125
  38. data/lib/{sequel_core → sequel}/adapters/shared/progress.rb +1 -2
  39. data/lib/{sequel_core → sequel}/adapters/shared/sqlite.rb +72 -67
  40. data/lib/{sequel_core → sequel}/adapters/sqlite.rb +11 -7
  41. data/lib/{sequel_core → sequel}/adapters/utils/date_format.rb +0 -0
  42. data/lib/{sequel_core → sequel}/adapters/utils/stored_procedures.rb +0 -0
  43. data/lib/{sequel_core → sequel}/adapters/utils/unsupported.rb +19 -0
  44. data/lib/{sequel_core → sequel}/connection_pool.rb +7 -5
  45. data/lib/sequel/core.rb +221 -0
  46. data/lib/{sequel_core → sequel}/core_sql.rb +91 -49
  47. data/lib/{sequel_core → sequel}/database.rb +264 -149
  48. data/lib/{sequel_core/schema/generator.rb → sequel/database/schema_generator.rb} +6 -2
  49. data/lib/{sequel_core/database/schema.rb → sequel/database/schema_methods.rb} +12 -12
  50. data/lib/sequel/database/schema_sql.rb +224 -0
  51. data/lib/{sequel_core → sequel}/dataset.rb +78 -236
  52. data/lib/{sequel_core → sequel}/dataset/convenience.rb +99 -61
  53. data/lib/{sequel_core/object_graph.rb → sequel/dataset/graph.rb} +16 -14
  54. data/lib/{sequel_core → sequel}/dataset/prepared_statements.rb +1 -1
  55. data/lib/{sequel_core → sequel}/dataset/sql.rb +150 -99
  56. data/lib/sequel/deprecated.rb +593 -0
  57. data/lib/sequel/deprecated_migration.rb +91 -0
  58. data/lib/sequel/exceptions.rb +48 -0
  59. data/lib/sequel/extensions/blank.rb +42 -0
  60. data/lib/{sequel_model → sequel/extensions}/inflector.rb +8 -1
  61. data/lib/{sequel_core → sequel/extensions}/migration.rb +1 -1
  62. data/lib/{sequel_core/dataset → sequel/extensions}/pagination.rb +0 -0
  63. data/lib/{sequel_core → sequel/extensions}/pretty_table.rb +7 -0
  64. data/lib/{sequel_core/dataset → sequel/extensions}/query.rb +7 -0
  65. data/lib/sequel/extensions/string_date_time.rb +47 -0
  66. data/lib/sequel/metaprogramming.rb +43 -0
  67. data/lib/sequel/model.rb +110 -0
  68. data/lib/sequel/model/associations.rb +1300 -0
  69. data/lib/sequel/model/base.rb +937 -0
  70. data/lib/sequel/model/deprecated.rb +204 -0
  71. data/lib/sequel/model/deprecated_hooks.rb +103 -0
  72. data/lib/sequel/model/deprecated_inflector.rb +335 -0
  73. data/lib/sequel/model/deprecated_validations.rb +388 -0
  74. data/lib/sequel/model/errors.rb +39 -0
  75. data/lib/{sequel_model → sequel/model}/exceptions.rb +4 -4
  76. data/lib/sequel/model/inflections.rb +208 -0
  77. data/lib/sequel/model/plugins.rb +76 -0
  78. data/lib/sequel/plugins/caching.rb +122 -0
  79. data/lib/sequel/plugins/hook_class_methods.rb +122 -0
  80. data/lib/sequel/plugins/schema.rb +53 -0
  81. data/lib/sequel/plugins/serialization.rb +117 -0
  82. data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
  83. data/lib/sequel/plugins/validation_class_methods.rb +384 -0
  84. data/lib/sequel/plugins/validation_helpers.rb +150 -0
  85. data/lib/{sequel_core → sequel}/sql.rb +125 -190
  86. data/lib/{sequel_core → sequel}/version.rb +2 -1
  87. data/lib/sequel_core.rb +1 -172
  88. data/lib/sequel_model.rb +1 -91
  89. data/spec/adapters/firebird_spec.rb +5 -5
  90. data/spec/adapters/informix_spec.rb +1 -1
  91. data/spec/adapters/mysql_spec.rb +128 -42
  92. data/spec/adapters/oracle_spec.rb +47 -19
  93. data/spec/adapters/postgres_spec.rb +64 -52
  94. data/spec/adapters/spec_helper.rb +1 -1
  95. data/spec/adapters/sqlite_spec.rb +12 -17
  96. data/spec/{sequel_core → core}/connection_pool_spec.rb +10 -10
  97. data/spec/{sequel_core → core}/core_ext_spec.rb +19 -19
  98. data/spec/{sequel_core → core}/core_sql_spec.rb +68 -71
  99. data/spec/{sequel_core → core}/database_spec.rb +135 -99
  100. data/spec/{sequel_core → core}/dataset_spec.rb +398 -242
  101. data/spec/{sequel_core → core}/expression_filters_spec.rb +13 -13
  102. data/spec/core/migration_spec.rb +263 -0
  103. data/spec/{sequel_core → core}/object_graph_spec.rb +10 -10
  104. data/spec/{sequel_core → core}/pretty_table_spec.rb +2 -2
  105. data/spec/{sequel_core → core}/schema_generator_spec.rb +0 -0
  106. data/spec/{sequel_core → core}/schema_spec.rb +8 -10
  107. data/spec/{sequel_core → core}/spec_helper.rb +29 -2
  108. data/spec/{sequel_core → core}/version_spec.rb +0 -0
  109. data/spec/extensions/blank_spec.rb +67 -0
  110. data/spec/extensions/caching_spec.rb +201 -0
  111. data/spec/{sequel_model/hooks_spec.rb → extensions/hook_class_methods_spec.rb} +8 -23
  112. data/spec/{sequel_model → extensions}/inflector_spec.rb +3 -0
  113. data/spec/{sequel_core → extensions}/migration_spec.rb +4 -4
  114. data/spec/extensions/pagination_spec.rb +99 -0
  115. data/spec/extensions/pretty_table_spec.rb +91 -0
  116. data/spec/extensions/query_spec.rb +85 -0
  117. data/spec/{sequel_model → extensions}/schema_spec.rb +22 -1
  118. data/spec/extensions/serialization_spec.rb +109 -0
  119. data/spec/extensions/single_table_inheritance_spec.rb +53 -0
  120. data/spec/{sequel_model → extensions}/spec_helper.rb +13 -4
  121. data/spec/extensions/string_date_time_spec.rb +93 -0
  122. data/spec/{sequel_model/validations_spec.rb → extensions/validation_class_methods_spec.rb} +15 -103
  123. data/spec/extensions/validation_helpers_spec.rb +291 -0
  124. data/spec/integration/dataset_test.rb +31 -0
  125. data/spec/integration/eager_loader_test.rb +17 -30
  126. data/spec/integration/schema_test.rb +8 -5
  127. data/spec/integration/spec_helper.rb +17 -0
  128. data/spec/integration/transaction_test.rb +68 -0
  129. data/spec/{sequel_model → model}/association_reflection_spec.rb +0 -0
  130. data/spec/{sequel_model → model}/associations_spec.rb +23 -10
  131. data/spec/{sequel_model → model}/base_spec.rb +29 -20
  132. data/spec/{sequel_model → model}/caching_spec.rb +16 -14
  133. data/spec/{sequel_model → model}/dataset_methods_spec.rb +0 -0
  134. data/spec/{sequel_model → model}/eager_loading_spec.rb +8 -8
  135. data/spec/model/hooks_spec.rb +472 -0
  136. data/spec/model/inflector_spec.rb +126 -0
  137. data/spec/{sequel_model → model}/model_spec.rb +25 -20
  138. data/spec/model/plugins_spec.rb +142 -0
  139. data/spec/{sequel_model → model}/record_spec.rb +121 -62
  140. data/spec/model/schema_spec.rb +92 -0
  141. data/spec/model/spec_helper.rb +124 -0
  142. data/spec/model/validations_spec.rb +1080 -0
  143. metadata +136 -107
  144. data/lib/sequel_core/core_ext.rb +0 -217
  145. data/lib/sequel_core/dataset/callback.rb +0 -13
  146. data/lib/sequel_core/dataset/schema.rb +0 -15
  147. data/lib/sequel_core/deprecated.rb +0 -26
  148. data/lib/sequel_core/exceptions.rb +0 -44
  149. data/lib/sequel_core/schema.rb +0 -2
  150. data/lib/sequel_core/schema/sql.rb +0 -325
  151. data/lib/sequel_model/association_reflection.rb +0 -267
  152. data/lib/sequel_model/associations.rb +0 -499
  153. data/lib/sequel_model/base.rb +0 -539
  154. data/lib/sequel_model/caching.rb +0 -82
  155. data/lib/sequel_model/dataset_methods.rb +0 -26
  156. data/lib/sequel_model/eager_loading.rb +0 -370
  157. data/lib/sequel_model/hooks.rb +0 -101
  158. data/lib/sequel_model/plugins.rb +0 -62
  159. data/lib/sequel_model/record.rb +0 -568
  160. data/lib/sequel_model/schema.rb +0 -49
  161. data/lib/sequel_model/validations.rb +0 -429
  162. data/spec/sequel_model/plugins_spec.rb +0 -80
@@ -0,0 +1,91 @@
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
@@ -0,0 +1,48 @@
1
+ module Sequel
2
+ # The default exception class for exceptions raised by Sequel.
3
+ # All exception classes defined by Sequel are descendants of this class.
4
+ class Error < ::StandardError
5
+ end
6
+
7
+ # Raised when the adapter requested doesn't exist or can't be loaded.
8
+ class AdapterNotFound < Error ; end
9
+
10
+ # Generic error raised by the database adapters, indicating a
11
+ # problem originating from the database server. Usually raised
12
+ # because incorrect SQL syntax is used.
13
+ class DatabaseError < Error; end
14
+
15
+ # Error raised when the Sequel is unable to connect to the database with the
16
+ # connection parameters it was given.
17
+ class DatabaseConnectionError < DatabaseError; end
18
+
19
+ # Error that should be raised by adapters when they determine that the connection
20
+ # to the database has been lost. Instructs the connection pool code to
21
+ # remove that connection from the pool so that other connections can be acquired
22
+ # automatically.
23
+ class DatabaseDisconnectError < DatabaseError; end
24
+
25
+ # Raised on an invalid operation, such as trying to update or delete
26
+ # a joined or grouped dataset.
27
+ class InvalidOperation < Error; end
28
+
29
+ # Raised when attempting an invalid type conversion.
30
+ class InvalidValue < Error ; end
31
+
32
+ # Raised when the connection pool cannot acquire a database connection
33
+ # before the timeout.
34
+ class PoolTimeout < Error ; end
35
+
36
+ # Exception that you should raise to signal a rollback of the current transaction.
37
+ # The transaction block will catch this exception, rollback the current transaction,
38
+ # and won't reraise it.
39
+ class Rollback < Error ; end
40
+
41
+ class Error
42
+ AdapterNotFound = Sequel::AdapterNotFound
43
+ InvalidOperation = Sequel::InvalidOperation
44
+ InvalidValue = Sequel::InvalidValue
45
+ PoolTimeoutError = Sequel::PoolTimeout
46
+ Rollback = Sequel::Rollback
47
+ end
48
+ end
@@ -0,0 +1,42 @@
1
+ class FalseClass
2
+ # false is always blank
3
+ def blank?
4
+ true
5
+ end
6
+ end
7
+
8
+ # Helpers from Metaid and a bit more
9
+ class Object
10
+ # Objects are blank if they respond true to empty?
11
+ def blank?
12
+ respond_to?(:empty?) && empty?
13
+ end
14
+ end
15
+
16
+ class NilClass
17
+ # nil is always blank
18
+ def blank?
19
+ true
20
+ end
21
+ end
22
+
23
+ class Numeric
24
+ # Numerics are never blank (not even 0)
25
+ def blank?
26
+ false
27
+ end
28
+ end
29
+
30
+ class String
31
+ # Strings are blank if they are empty or include only whitespace
32
+ def blank?
33
+ strip.empty?
34
+ end
35
+ end
36
+
37
+ class TrueClass
38
+ # true is never blank
39
+ def blank?
40
+ false
41
+ end
42
+ end
@@ -21,7 +21,9 @@ class String
21
21
  module Inflections
22
22
  @plurals, @singulars, @uncountables = [], [], []
23
23
 
24
- metaattr_reader :plurals, :singulars, :uncountables
24
+ class << self
25
+ attr_reader :plurals, :singulars, :uncountables
26
+ end
25
27
 
26
28
  # Clears the loaded inflections within a given scope (default is :all). Give the scope as a symbol of the inflection type,
27
29
  # the options are: :plurals, :singulars, :uncountables
@@ -30,6 +32,7 @@ class String
30
32
  # clear :all
31
33
  # clear :plurals
32
34
  def self.clear(scope = :all)
35
+ Sequel::Inflections.clear(scope)
33
36
  case scope
34
37
  when :all
35
38
  @plurals, @singulars, @uncountables = [], [], []
@@ -45,6 +48,7 @@ class String
45
48
  # irregular 'octopus', 'octopi'
46
49
  # irregular 'person', 'people'
47
50
  def self.irregular(singular, plural)
51
+ Sequel::Inflections.irregular(singular, plural)
48
52
  plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
49
53
  singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
50
54
  end
@@ -55,6 +59,7 @@ class String
55
59
  # Example:
56
60
  # plural(/(x|ch|ss|sh)$/i, '\1es')
57
61
  def self.plural(rule, replacement)
62
+ Sequel::Inflections.plural(rule, replacement)
58
63
  @plurals.insert(0, [rule, replacement])
59
64
  end
60
65
 
@@ -64,6 +69,7 @@ class String
64
69
  # Example:
65
70
  # singular(/([^aeiouy]|qu)ies$/i, '\1y')
66
71
  def self.singular(rule, replacement)
72
+ Sequel::Inflections.singular(rule, replacement)
67
73
  @singulars.insert(0, [rule, replacement])
68
74
  end
69
75
 
@@ -74,6 +80,7 @@ class String
74
80
  # uncountable "money", "information"
75
81
  # uncountable %w( money information rice )
76
82
  def self.uncountable(*words)
83
+ Sequel::Inflections.uncountable(*words)
77
84
  (@uncountables << words).flatten!
78
85
  end
79
86
 
@@ -35,7 +35,7 @@ module Sequel
35
35
  # To apply a migration to a database, you can invoke the #apply with
36
36
  # the target database instance and the direction :up or :down, e.g.:
37
37
  #
38
- # DB = Sequel.open ('sqlite://mydb')
38
+ # DB = Sequel.connect('sqlite://mydb')
39
39
  # CreateSessions.apply(DB, :up)
40
40
  #
41
41
  # See Sequel::Schema::Generator for the syntax to use for creating tables,
@@ -1,4 +1,11 @@
1
1
  module Sequel
2
+ class Dataset
3
+ # Pretty prints the records in the dataset as plain-text table.
4
+ def print(*cols)
5
+ Sequel::PrettyTable.print(naked.all, cols.empty? ? columns : cols)
6
+ end
7
+ end
8
+
2
9
  module PrettyTable
3
10
  # Prints nice-looking plain-text tables via puts
4
11
  #
@@ -1,4 +1,11 @@
1
1
  module Sequel
2
+ class Database
3
+ # Return a dataset modified by the query block
4
+ def query(&block)
5
+ dataset.query(&block)
6
+ end
7
+ end
8
+
2
9
  class Dataset
3
10
  # Translates a query block into a dataset. Query blocks can be useful
4
11
  # when expressing complex SELECT statements, e.g.:
@@ -0,0 +1,47 @@
1
+ # This file contains the previous extensions to String for date/time
2
+ # conversions. These are provided mainly for backward compatibility,
3
+ # Sequel now uses a module level method instead of extending string
4
+ # to handle the internal conversions.
5
+
6
+ class String
7
+ # Converts a string into a Date object.
8
+ def to_date
9
+ begin
10
+ Date.parse(self, Sequel.convert_two_digit_years)
11
+ rescue => e
12
+ raise Sequel::InvalidValue, "Invalid Date value '#{self}' (#{e.message})"
13
+ end
14
+ end
15
+
16
+ # Converts a string into a DateTime object.
17
+ def to_datetime
18
+ begin
19
+ DateTime.parse(self, Sequel.convert_two_digit_years)
20
+ rescue => e
21
+ raise Sequel::InvalidValue, "Invalid DateTime value '#{self}' (#{e.message})"
22
+ end
23
+ end
24
+
25
+ # Converts a string into a Time or DateTime object, depending on the
26
+ # value of Sequel.datetime_class
27
+ def to_sequel_time
28
+ begin
29
+ if Sequel.datetime_class == DateTime
30
+ DateTime.parse(self, Sequel.convert_two_digit_years)
31
+ else
32
+ Sequel.datetime_class.parse(self)
33
+ end
34
+ rescue => e
35
+ raise Sequel::InvalidValue, "Invalid #{Sequel.datetime_class} value '#{self}' (#{e.message})"
36
+ end
37
+ end
38
+
39
+ # Converts a string into a Time object.
40
+ def to_time
41
+ begin
42
+ Time.parse(self)
43
+ rescue => e
44
+ raise Sequel::InvalidValue, "Invalid Time value '#{self}' (#{e.message})"
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,43 @@
1
+ module Sequel
2
+ # Contains methods that ease metaprogramming, used by some of Sequel's classes.
3
+ module Metaprogramming
4
+ # Add methods to the object's metaclass
5
+ def meta_def(name, &block)
6
+ meta_eval{define_method(name, &block)}
7
+ end
8
+
9
+ private
10
+
11
+ # Make a singleton/class attribute accessor method(s).
12
+ # Replaces the construct:
13
+ #
14
+ # class << self
15
+ # attr_accessor *meths
16
+ # end
17
+ def metaattr_accessor(*meths)
18
+ meta_eval{attr_accessor(*meths)}
19
+ end
20
+
21
+ # Make a singleton/class attribute reader method(s).
22
+ # Replaces the construct:
23
+ #
24
+ # class << self
25
+ # attr_reader *meths
26
+ # end
27
+ def metaattr_reader(*meths)
28
+ meta_eval{attr_reader(*meths)}
29
+ end
30
+
31
+ # Evaluate the block in the context of the object's metaclass
32
+ def meta_eval(&block)
33
+ metaclass.instance_eval(&block)
34
+ end
35
+
36
+ # The hidden singleton lurks behind everyone
37
+ def metaclass
38
+ class << self
39
+ self
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,110 @@
1
+ require 'sequel/core'
2
+
3
+ module Sequel
4
+ # Lets you create a Model subclass with its dataset already set.
5
+ # source can be an existing dataset or a symbol (in which case
6
+ # it will create a dataset using the default database with
7
+ # the given symbol as the table name).
8
+ #
9
+ # The purpose of this method is to set the dataset automatically
10
+ # for a model class, if the table name doesn't match the implicit
11
+ # name. This is neater than using set_dataset inside the class,
12
+ # doesn't require a bogus query for the schema, and allows
13
+ # it to work correctly in a system that uses code reloading.
14
+ #
15
+ # Example:
16
+ # class Comment < Sequel::Model(:something)
17
+ # table_name # => :something
18
+ # end
19
+ def self.Model(source)
20
+ Model::ANONYMOUS_MODEL_CLASSES[source] ||= Class.new(Model).set_dataset(source)
21
+ end
22
+
23
+ # Sequel::Model is an object relational mapper built on top of Sequel core. Each
24
+ # model class is backed by a dataset instance, and many dataset methods can be
25
+ # called directly on the class. Model datasets return rows as model instances,
26
+ # which have fairly standard ORM instance behavior.
27
+ #
28
+ # Sequel::Model is built completely out of plugins, the only method not part of a
29
+ # plugin is the plugin method itself. Plugins can override any class, instance, or
30
+ # dataset method defined by a previous plugin and call super to get the default
31
+ # behavior.
32
+ #
33
+ # You can set the SEQUEL_NO_ASSOCIATIONS constant or environment variable to
34
+ # make Sequel not load the associations plugin by default.
35
+ class Model
36
+ # Map that stores model classes created with Sequel::Model(), to allow the reopening
37
+ # of classes when dealing with code reloading.
38
+ ANONYMOUS_MODEL_CLASSES = {}
39
+
40
+ # Class methods added to model that call the method of the same name on the dataset
41
+ DATASET_METHODS = %w'<< all avg count delete distinct eager eager_graph
42
+ each each_page empty? except exclude filter first from from_self
43
+ full_outer_join get graph group group_and_count group_by having import
44
+ inner_join insert insert_multiple intersect interval join join_table
45
+ last left_outer_join limit map multi_insert naked order order_by
46
+ order_more paginate print query range reverse_order right_outer_join
47
+ select select_all select_more server set set_graph_aliases
48
+ single_value to_csv to_hash transform union unfiltered unordered
49
+ update where with_sql'.map{|x| x.to_sym}
50
+
51
+ # Class instance variables to set to nil when a subclass is created, for -w compliance
52
+ EMPTY_INSTANCE_VARIABLES = [:@overridable_methods_module, :@db]
53
+
54
+ # Empty instance methods to create that the user can override to get hook/callback behavior.
55
+ # Just like any other method defined by Sequel, if you override one of these, you should
56
+ # call super to get the default behavior (while empty by default, they can also be defined
57
+ # by plugins).
58
+ HOOKS = [:after_initialize, :before_create, :after_create, :before_update,
59
+ :after_update, :before_save, :after_save, :before_destroy, :after_destroy,
60
+ :before_validation, :after_validation]
61
+
62
+ # Class instance variables that are inherited in subclasses. If the value is :dup, dup is called
63
+ # on the superclass's instance variable when creating the instance variable in the subclass.
64
+ # If the value is nil, the superclass's instance variable is used directly in the subclass.
65
+ INHERITED_INSTANCE_VARIABLES = {:@allowed_columns=>:dup, :@dataset_methods=>:dup,
66
+ :@dataset_method_modules=>:dup, :@primary_key=>nil, :@use_transactions=>nil,
67
+ :@raise_on_save_failure=>nil, :@restricted_columns=>:dup, :@restrict_primary_key=>nil,
68
+ :@simple_pk=>nil, :@simple_table=>nil, :@strict_param_setting=>nil,
69
+ :@typecast_empty_string_to_nil=>nil, :@typecast_on_assignment=>nil,
70
+ :@raise_on_typecast_failure=>nil}
71
+
72
+ # Regexp that determines if a method name is normal in the sense that
73
+ # it could be called directly in ruby code without using send. Used to
74
+ # avoid problems when using eval with a string to define methods.
75
+ NORMAL_METHOD_NAME_REGEXP = /\A[A-Za-z_][A-Za-z0-9_]*\z/
76
+
77
+ # The setter methods (methods ending with =) that are never allowed
78
+ # to be called automatically via set/update/new/etc..
79
+ RESTRICTED_SETTER_METHODS = %w"== === []= taguri= typecast_empty_string_to_nil= typecast_on_assignment= strict_param_setting= raise_on_save_failure= raise_on_typecast_failure="
80
+
81
+ # Regular expression that determines if the method is a valid setter name
82
+ # (i.e. it ends with =).
83
+ SETTER_METHOD_REGEXP = /=\z/
84
+
85
+ @allowed_columns = nil
86
+ @db = nil
87
+ @db_schema = nil
88
+ @dataset_method_modules = []
89
+ @dataset_methods = {}
90
+ @overridable_methods_module = nil
91
+ @primary_key = :id
92
+ @raise_on_save_failure = true
93
+ @raise_on_typecast_failure = true
94
+ @restrict_primary_key = true
95
+ @restricted_columns = nil
96
+ @simple_pk = nil
97
+ @simple_table = nil
98
+ @strict_param_setting = true
99
+ @typecast_empty_string_to_nil = true
100
+ @typecast_on_assignment = true
101
+ @use_transactions = true
102
+ end
103
+
104
+ require %w"inflections plugins base exceptions errors", "model"
105
+ if !defined?(::SEQUEL_NO_ASSOCIATIONS) && !ENV.has_key?('SEQUEL_NO_ASSOCIATIONS')
106
+ require 'associations', 'model'
107
+ Model.plugin Model::Associations
108
+ end
109
+ require 'deprecated', 'model'
110
+ end