sequel 2.11.0 → 2.12.0

Sign up to get free protection for your applications and to get access to all the features.
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