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
data/Rakefile CHANGED
@@ -1,46 +1,45 @@
1
1
  require "rake"
2
2
  require "rake/clean"
3
3
  require "rake/gempackagetask"
4
- require "spec/rake/spectask"
5
4
  begin
6
5
  require "hanna/rdoctask"
7
6
  rescue LoadError
8
7
  require "rake/rdoctask"
9
8
  end
10
- require "fileutils"
11
- require "lib/sequel_core/version"
12
-
13
- include FileUtils
14
9
 
15
10
  NAME = 'sequel'
16
- VERS = Sequel.version
17
- CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage", "www/public/*.html"]
18
- RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', \
19
- 'Sequel: The Database Toolkit for Ruby', '--main', 'README.rdoc']
11
+ VERS = lambda do
12
+ require "lib/sequel/version"
13
+ Sequel.version
14
+ end
15
+ CLEAN.include ["**/.*.sw?", "pkg", ".config", "rdoc", "coverage", "www/public/*.html", "www/public/rdoc*"]
16
+ RDOC_DEFAULT_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', 'Sequel: The Database Toolkit for Ruby']
17
+ RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
20
18
 
21
19
  # Gem Packaging and Release
22
20
 
23
- desc "Packages sequel"
24
- task :package=>[:clean]
25
21
  spec = Gem::Specification.new do |s|
26
22
  s.name = NAME
27
23
  s.rubyforge_project = 'sequel'
28
- s.version = VERS
24
+ s.version = VERS.call
29
25
  s.platform = Gem::Platform::RUBY
30
26
  s.has_rdoc = true
31
27
  s.extra_rdoc_files = ["README.rdoc", "CHANGELOG", "COPYING"] + Dir["doc/*.rdoc"] + Dir['doc/release_notes/*.txt']
32
- s.rdoc_options += RDOC_OPTS
28
+ s.rdoc_options += RDOC_OPTS
33
29
  s.summary = "The Database Toolkit for Ruby"
34
30
  s.description = s.summary
35
31
  s.author = "Jeremy Evans"
36
32
  s.email = "code@jeremyevans.net"
37
33
  s.homepage = "http://sequel.rubyforge.org"
38
34
  s.required_ruby_version = ">= 1.8.4"
39
- s.files = %w(COPYING CHANGELOG README.rdoc Rakefile) + Dir.glob("{bin,doc,spec,lib}/**/*")
35
+ s.files = %w(COPYING CHANGELOG README.rdoc Rakefile) + Dir["{bin,doc,spec,lib}/**/*"]
40
36
  s.require_path = "lib"
41
37
  s.bindir = 'bin'
42
38
  s.executables << 'sequel'
43
39
  end
40
+
41
+ desc "Packages sequel"
42
+ task :package=>[:clean]
44
43
  Rake::GemPackageTask.new(spec) do |p|
45
44
  p.need_tar = true
46
45
  p.gem_spec = spec
@@ -48,12 +47,7 @@ end
48
47
 
49
48
  desc "Install sequel gem"
50
49
  task :install=>[:package] do
51
- sh %{sudo gem install pkg/#{NAME}-#{VERS} --local}
52
- end
53
-
54
- desc "Install sequel gem without RDoc"
55
- task :install_no_docs=>[:package] do
56
- sh %{sudo gem install pkg/#{NAME}-#{VERS} --no-rdoc --no-ri --local}
50
+ sh %{sudo gem install pkg/#{NAME}-#{VERS.call} --local}
57
51
  end
58
52
 
59
53
  desc "Uninstall sequel gem"
@@ -61,11 +55,11 @@ task :uninstall=>[:clean] do
61
55
  sh %{sudo gem uninstall #{NAME}}
62
56
  end
63
57
 
64
- desc "Upload sequel and sequel_core gems to rubyforge"
58
+ desc "Upload sequel gem to rubyforge"
65
59
  task :release=>[:package] do
66
60
  sh %{rubyforge login}
67
- sh %{rubyforge add_release sequel #{NAME} #{VERS} pkg/#{NAME}-#{VERS}.tgz}
68
- sh %{rubyforge add_file sequel #{NAME} #{VERS} pkg/#{NAME}-#{VERS}.gem}
61
+ sh %{rubyforge add_release sequel #{NAME} #{VERS.call} pkg/#{NAME}-#{VERS.call}.tgz}
62
+ sh %{rubyforge add_file sequel #{NAME} #{VERS.call} pkg/#{NAME}-#{VERS.call}.gem}
69
63
  end
70
64
 
71
65
  ### RDoc
@@ -78,73 +72,103 @@ end
78
72
 
79
73
  ### Website
80
74
 
81
- desc "Update Non-RDoc section of sequel.rubyforge.org"
82
- task :website_base do
75
+ desc "Make local version of website"
76
+ task :website do
83
77
  sh %{www/make_www.rb}
84
- sh %{scp -r www/public/* rubyforge.org:/var/www/gforge-projects/sequel/}
85
78
  end
86
79
 
87
- desc "Update RDoc section of sequel.rubyforge.org"
88
- task :website_rdoc=>[:rerdoc] do
89
- sh %{scp -r rdoc/* rubyforge.org:/var/www/gforge-projects/sequel/rdoc/}
90
- end
91
-
92
- desc "Update sequel.rubyforge.org"
93
- task :website=>[:website_base, :website_rdoc]
94
-
95
- ### Specs
80
+ desc "Make rdoc for website"
81
+ task :website_rdoc=>[:website_rdoc_main, :website_rdoc_adapters, :website_rdoc_plugins]
96
82
 
97
- lib_dir = File.join(File.dirname(__FILE__), 'lib')
98
- fixRUBYLIB = Proc.new{ENV['RUBYLIB'] ? (ENV['RUBYLIB'] += ":#{lib_dir}") : (ENV['RUBYLIB'] = lib_dir)}
99
- sequel_core_specs = "spec/sequel_core/*_spec.rb"
100
- sequel_model_specs = "spec/sequel_model/*_spec.rb"
101
- spec_opts = proc{File.read("spec/spec.opts").split("\n")}
102
- rcov_opts = proc{File.read("spec/rcov.opts").split("\n")}
103
-
104
- desc "Run core and model specs with coverage"
105
- Spec::Rake::SpecTask.new("spec_coverage") do |t|
106
- fixRUBYLIB.call
107
- t.spec_files = FileList[sequel_core_specs, sequel_model_specs]
108
- t.spec_opts = spec_opts.call
109
- t.rcov_opts = rcov_opts.call
110
- t.rcov = true
83
+ Rake::RDocTask.new(:website_rdoc_main) do |rdoc|
84
+ rdoc.rdoc_dir = "www/public/rdoc"
85
+ rdoc.options += RDOC_OPTS
86
+ rdoc.rdoc_files.add %w"README.rdoc CHANGELOG COPYING lib/*.rb lib/sequel/*.rb lib/sequel/{dataset,database,model}/*.rb doc/*.rdoc doc/release_notes/*.txt"
111
87
  end
112
88
 
113
- desc "Run core and model specs"
114
- task :default => [:spec]
115
- Spec::Rake::SpecTask.new("spec") do |t|
116
- fixRUBYLIB.call
117
- t.spec_files = FileList[sequel_core_specs, sequel_model_specs]
118
- t.spec_opts = spec_opts.call
89
+ Rake::RDocTask.new(:website_rdoc_adapters) do |rdoc|
90
+ rdoc.rdoc_dir = "www/public/rdoc-adapters"
91
+ rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel'
92
+ rdoc.rdoc_files.add %w"lib/sequel/adapters/**/*.rb"
119
93
  end
120
94
 
121
- desc "Run core specs"
122
- Spec::Rake::SpecTask.new("spec_core") do |t|
123
- fixRUBYLIB.call
124
- t.spec_files = FileList[sequel_core_specs]
125
- t.spec_opts = spec_opts.call
95
+ Rake::RDocTask.new(:website_rdoc_plugins) do |rdoc|
96
+ rdoc.rdoc_dir = "www/public/rdoc-plugins"
97
+ rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel'
98
+ rdoc.rdoc_files.add %w"lib/sequel/{extensions,plugins}/**/*.rb"
126
99
  end
127
100
 
128
- desc "Run model specs"
129
- Spec::Rake::SpecTask.new("spec_model") do |t|
130
- fixRUBYLIB.call
131
- t.spec_files = FileList[sequel_model_specs]
132
- t.spec_opts = spec_opts.call
101
+ desc "Update Non-RDoc section of sequel.rubyforge.org"
102
+ task :website_rf_base=>[:website] do
103
+ sh %{rsync -rt www/public/*.html rubyforge.org:/var/www/gforge-projects/sequel/}
133
104
  end
134
105
 
135
- desc "Run integration tests"
136
- Spec::Rake::SpecTask.new("integration") do |t|
137
- fixRUBYLIB.call
138
- t.spec_files = FileList["spec/integration/*_test.rb"]
139
- t.spec_opts = spec_opts.call
106
+ desc "Update sequel.rubyforge.org"
107
+ task :website_rf=>[:website, :website_rdoc] do
108
+ sh %{rsync -rvt www/public/* rubyforge.org:/var/www/gforge-projects/sequel/}
140
109
  end
141
110
 
142
- %w'postgres sqlite mysql informix oracle ado'.each do |adapter|
143
- desc "Run #{adapter} specs without coverage"
144
- Spec::Rake::SpecTask.new("spec_#{adapter}") do |t|
145
- t.spec_files = ["spec/adapters/#{adapter}_spec.rb"]
111
+ ### Specs
112
+
113
+ begin
114
+ require "spec/rake/spectask"
115
+
116
+ spec_opts = lambda do
117
+ lib_dir = File.join(File.dirname(__FILE__), 'lib')
118
+ ENV['RUBYLIB'] ? (ENV['RUBYLIB'] += ":#{lib_dir}") : (ENV['RUBYLIB'] = lib_dir)
119
+ File.read("spec/spec.opts").split("\n")
120
+ end
121
+
122
+ rcov_opts = lambda do
123
+ [true, File.read("spec/rcov.opts").split("\n")]
124
+ end
125
+
126
+ desc "Run core and model specs with coverage"
127
+ Spec::Rake::SpecTask.new("spec_coverage") do |t|
128
+ t.spec_files = Dir["spec/{core,model}/*_spec.rb"]
129
+ t.spec_opts = spec_opts.call
130
+ t.rcov, t.rcov_opts = rcov_opts.call
131
+ end
132
+
133
+ desc "Run core and model specs"
134
+ task :default => [:spec]
135
+ Spec::Rake::SpecTask.new("spec") do |t|
136
+ t.spec_files = Dir["spec/{core,model}/*_spec.rb"]
137
+ t.spec_opts = spec_opts.call
138
+ end
139
+
140
+ desc "Run core specs"
141
+ Spec::Rake::SpecTask.new("spec_core") do |t|
142
+ t.spec_files = Dir["spec/core/*_spec.rb"]
146
143
  t.spec_opts = spec_opts.call
147
144
  end
145
+
146
+ desc "Run model specs"
147
+ Spec::Rake::SpecTask.new("spec_model") do |t|
148
+ t.spec_files = Dir["spec/model/*_spec.rb"]
149
+ t.spec_opts = spec_opts.call
150
+ end
151
+
152
+ desc "Run extension/plugin specs"
153
+ Spec::Rake::SpecTask.new("spec_plugin") do |t|
154
+ t.spec_files = Dir["spec/extensions/*_spec.rb"]
155
+ t.spec_opts = spec_opts.call
156
+ end
157
+
158
+ desc "Run integration tests"
159
+ Spec::Rake::SpecTask.new("integration") do |t|
160
+ t.spec_files = FileList["spec/integration/*_test.rb"]
161
+ t.spec_opts = spec_opts.call
162
+ end
163
+
164
+ %w'postgres sqlite mysql informix oracle ado'.each do |adapter|
165
+ desc "Run #{adapter} specs without coverage"
166
+ Spec::Rake::SpecTask.new("spec_#{adapter}") do |t|
167
+ t.spec_files = ["spec/adapters/#{adapter}_spec.rb"]
168
+ t.spec_opts = spec_opts.call
169
+ end
170
+ end
171
+ rescue LoadError
148
172
  end
149
173
 
150
174
  desc "check documentation coverage"
@@ -154,13 +178,9 @@ end
154
178
 
155
179
  ### Statistics
156
180
 
157
- STATS_DIRECTORIES = [
158
- %w(Code lib/),
159
- %w(Spec spec),
160
- ].collect { |name, dir| [ name, "./#{dir}" ] }.select { |name, dir| File.directory?(dir) }
161
-
162
181
  desc "Report code statistics (KLOCs, etc) from the application"
163
182
  task :stats do
183
+ STATS_DIRECTORIES = [%w(Code lib/), %w(Spec spec)].map{|name, dir| [ name, "./#{dir}" ] }.select { |name, dir| File.directory?(dir)}
164
184
  require "extra/stats"
165
185
  verbose = true
166
186
  CodeStatistics.new(*STATS_DIRECTORIES).to_s
@@ -168,5 +188,5 @@ end
168
188
 
169
189
  desc "Print Sequel version"
170
190
  task :version do
171
- puts VERS
191
+ puts VERS.call
172
192
  end
data/bin/sequel CHANGED
@@ -63,7 +63,7 @@ opts.parse!
63
63
 
64
64
  db = ARGV.shift
65
65
 
66
- if db.blank?
66
+ if db.nil? || db.empty?
67
67
  puts opts
68
68
  exit 1
69
69
  end
@@ -88,6 +88,7 @@ begin
88
88
  DB = Sequel.connect(*(db_config ? [db_config] : [db, db_opts]))
89
89
  DB.test_connection
90
90
  if migrate_dir
91
+ require 'sequel/extensions/migration'
91
92
  Sequel::Migrator.apply(DB, migrate_dir, migrate_ver)
92
93
  exit
93
94
  end
@@ -4,7 +4,7 @@ Sequel::Model has the most powerful and flexible associations of any ruby ORM.
4
4
 
5
5
  "Extraordinary claims require extraordinary proof" - Carl Sagan
6
6
 
7
- ==Background: Sequel::Model association options
7
+ == Background: Sequel::Model association options
8
8
 
9
9
  There are a bunch of advanced association options that are available to
10
10
  handle the other-than-bog-standard cases. First we'll go over some of
@@ -35,11 +35,10 @@ JOINing to the join table in a many_to_many association).
35
35
  condition. The block is passed the associated table alias, current model
36
36
  alias, and array of previous joins.
37
37
  - :graph_only_conditions - Use these conditions instead of the standard
38
- association conditions. This is necessary when the standard keys it uses are
39
- not correct for the association (such as an association that doesn't use
40
- primary keys). You can also use this to have a JOIN USING (array of
41
- symbols), or a NATURAL or CROSS JOIN (nil, with the appropriate
42
- :graph_join_type).
38
+ association conditions. This is necessary when you don't want to have an
39
+ equal condition between the foreign key and primary key of the tables.
40
+ You can also use this to have a JOIN USING (array of symbols), or a NATURAL
41
+ or CROSS JOIN (nil, with the appropriate :graph_join_type).
43
42
 
44
43
  These can be used like this:
45
44
 
@@ -55,21 +54,15 @@ These can be used like this:
55
54
  Artist.one_to_many :gold_albums, :class=>:Album, \
56
55
  :graph_block=>proc{|j,lj,js| :copies_sold.qualify(j) > 500000}
57
56
 
58
- # Handles the case where the artist is associated to the album by an
59
- # artist_name column in the albums table, when name is not the primary key
60
- # of the artists table
57
+ # Handles the case where the to tables are associated by a case insensitive name string
61
58
  Artist.one_to_many :albums, :key=>:artist_name, \
62
- :graph_only_conditions=>{:artist_name=>:name}
59
+ :graph_only_conditions=>nil, \
60
+ :graph_block=>proc{|j,lj,js| {:lower.sql_function(artist_name.qualify(j))=>:lower.sql_function(name.qualify(lj))}}
63
61
 
64
- # Handles the above case, but where :artist_name is used in both tables,
65
- # via a JOIN USING
62
+ # Handles the case where both key columns have the name artist_name, and you want to use
63
+ # a JOIN USING
66
64
  Artist.one_to_many :albums, :key=>:artist_name, :graph_only_conditions=>[:artist_name]
67
65
 
68
- # Handles the case where all columns in both tables are uniquely named, except
69
- # for the ones that handle associations
70
- Artist.one_to_many :albums, :key=>:artist_name, :graph_only_conditions=>nil, \
71
- :graph_join_type=>:natural
72
-
73
66
  Remember, using #eager_graph is generally only necessary when you need to
74
67
  filter/order based on columns in an associated table, it is recommended to
75
68
  use #eager for eager loading if possible.
@@ -91,7 +84,7 @@ associations that are specified by multiple keys, or do multiple
91
84
  queries depending on the content of the records (which would be
92
85
  necessary for polymorphic associations). Inside the :eager_loader
93
86
  proc, you should get the related objects and populate the
94
- associations for all objects in the array of records. The hash
87
+ associations cache for all objects in the array of records. The hash
95
88
  of dependent associations is available for you to cascade the eager
96
89
  loading down multiple levels, but it is up to you to use it. The
97
90
  key_hash is a performance enhancement that is used by the default
@@ -113,13 +106,13 @@ give an example:
113
106
  Using these options, you can build associations Sequel doesn't natively support,
114
107
  and still be able to use the same eager loading features that you are used to.
115
108
 
116
- ==ActiveRecord associations
109
+ == ActiveRecord associations
117
110
 
118
111
  Sequel supports all of associations that ActiveRecord supports, one way or
119
112
  another. Sometimes this requires more code, as Sequel is a toolkit and not
120
113
  a swiss army chainsaw.
121
114
 
122
- ===Association callbacks
115
+ === Association callbacks
123
116
 
124
117
  Sequel supports the same callbacks that ActiveRecord does: :before_add,
125
118
  :before_remove, :after_add, and :after_remove. It also supports a
@@ -142,9 +135,9 @@ remove callbacks on the existing object and the add callbacks on the
142
135
  new object. The remove callback calls are placed around the add
143
136
  callback calls.
144
137
 
145
- ===Association extensions
138
+ === Association extensions
146
139
 
147
- All associations come with a _dataset method that can be further filtered or
140
+ All associations come with an association_dataset method that can be further filtered or
148
141
  otherwise modified:
149
142
 
150
143
  class Author < Sequel::Model
@@ -159,8 +152,7 @@ association_reflection method:
159
152
 
160
153
  module FindOrCreate
161
154
  def find_or_create(vals)
162
- first(vals) || association_reflection.associated_class. \
163
- create(vals.merge(association_reflection[:key]=>model_object.id))
155
+ first(vals) || model.create(vals.merge(association_reflection[:key]=>model_object.id))
164
156
  end
165
157
  end
166
158
  class Author < Sequel::Model
@@ -168,7 +160,7 @@ association_reflection method:
168
160
  end
169
161
  Author.first.authorships_dataset.find_or_create(:name=>'Blah', :number=>10)
170
162
 
171
- ===has_many :through associations
163
+ === has_many :through associations
172
164
 
173
165
  many_to_many handles the usual case of a has_many :through with a belongs_to in
174
166
  the associated model. It doesn't break on the case where the join table is a
@@ -291,7 +283,7 @@ in the associations cache for each object, which ActiveRecord won't do for you.
291
283
  The reason you would want to do this is that then firm.invoices.first.firm or
292
284
  firm.invoices.first.client doesn't do another query to get the firm/client.
293
285
 
294
- ===Polymorphic Associations
286
+ === Polymorphic Associations
295
287
 
296
288
  Polymorphic associations are really a design flaw. The only advantage
297
289
  polymorphic associations offer is that they require fewer join tables.
@@ -404,13 +396,13 @@ Sequel::Model:
404
396
  @asset.attachable = @post
405
397
  @asset.attachable = @note
406
398
 
407
- ==More advanced associations
399
+ == More advanced associations
408
400
 
409
401
  So far, we've only shown that Sequel::Model has associations as powerful as
410
402
  ActiveRecord's. Now we will show how Sequel::Model's associations are more
411
403
  powerful.
412
404
 
413
- ===many_to_one/one_to_many not referencing primary key
405
+ === many_to_one/one_to_many not referencing primary key
414
406
 
415
407
  This can now be handled easily in Sequel using the :primary_key association
416
408
  option. However, this example shows how the association was possible before
@@ -469,7 +461,7 @@ design, but sometimes you have to play with the cards you are dealt).
469
461
  end
470
462
  end
471
463
 
472
- ===Joining on multiple keys
464
+ === Joining on multiple keys
473
465
 
474
466
  Let's say you have two tables that are associated with each other with multiple
475
467
  keys. For example:
@@ -511,7 +503,7 @@ keys. For example:
511
503
  end)
512
504
  end
513
505
 
514
- ===Tree - All Ancestors and Descendents
506
+ === Tree - All Ancestors and Descendents
515
507
 
516
508
  Let's say you want to store a tree relationship in your database, it's pretty
517
509
  simple:
@@ -580,8 +572,7 @@ without knowing the depth of the tree?
580
572
  end)
581
573
  end
582
574
 
583
-
584
- ===Joining multiple keys to a single key, through a third table
575
+ === Joining multiple keys to a single key, through a third table
585
576
 
586
577
  Let's say you have a database, of songs, lyrics, and artists. Each song
587
578
  may or may not have a lyric (most songs are instrumental). The lyric can be
data/doc/cheat_sheet.rdoc CHANGED
@@ -7,12 +7,12 @@
7
7
 
8
8
  DB = Sequel.sqlite('my_blog.db')
9
9
  DB = Sequel.connect('postgres://user:password@localhost/my_db')
10
- DB = Sequel.mysql('my_db', :user => 'user', :password => 'password', :host => 'localhost')
10
+ DB = Sequel.postgres('my_db', :user => 'user', :password => 'password', :host => 'localhost')
11
11
  DB = Sequel.ado('mydb')
12
12
 
13
13
  == Open an SQLite memory database
14
14
 
15
- Without a filename argument, the sqlite adapter will setup a new sqlite database in RAM.
15
+ Without a filename argument, the sqlite adapter will setup a new sqlite database in memory.
16
16
 
17
17
  DB = Sequel.sqlite
18
18
 
@@ -26,56 +26,49 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
26
26
  == Using raw SQL
27
27
 
28
28
  DB << "CREATE TABLE users (name VARCHAR(255) NOT NULL, age INT(3) NOT NULL)"
29
+ dataset = DB["SELECT age FROM users WHERE name = ?", name]
30
+ dataset.map(:age)
29
31
  DB.fetch("SELECT name FROM users") do |row|
30
32
  p r[:name]
31
33
  end
32
- dataset = DB["SELECT age FROM users WHERE name = ?", name]
33
- dataset.print
34
- dataset.map(:age)
35
34
 
36
35
  == Create a dataset
37
36
 
38
37
  dataset = DB[:items]
39
- dataset = DB.dataset.from(:items)
38
+ dataset = DB.from(:items)
40
39
 
41
40
  == Most dataset methods are chainable
42
41
 
43
42
  dataset = DB[:managers].where(:salary => 5000..10000).order(:name, :department)
44
- # or
45
- dataset = DB.query do
46
- from :managers
47
- where :salary => 5000..10000
48
- order :name, :department
49
- end
50
43
 
51
44
  == Insert rows
52
45
 
53
46
  dataset.insert(:name => 'Sharon', :grade => 50)
54
- dataset << {:name => 'Sharon', :grade => 50} # same effect as above
55
47
 
56
48
  == Retrieve rows
57
49
 
58
- dataset.each {|r| p r}
50
+ dataset.each{|r| p r}
59
51
  dataset.all #=> [{...}, {...}, ...]
60
52
  dataset.first
61
- dataset.order(:name).last # works only for ordered datasets
62
53
 
63
54
  == Update/Delete rows
64
55
 
65
- dataset.filter(:active => false).delete
56
+ dataset.filter(~:active).delete
66
57
  dataset.filter('price < ?', 100).update(:active => true)
67
58
 
68
59
  == Datasets are Enumerable
69
60
 
70
- dataset.map {|r| r[:name]}
71
- dataset.map(:name) # same effect as above
61
+ dataset.map{|r| r[:name]}
62
+ dataset.map(:name) # same as above
72
63
 
73
64
  dataset.inject(0){|sum, r| sum + r[:value]}
65
+ dataset.sum(:value) # same as above
74
66
 
75
67
  == Filtering (see also doc/dataset_filtering.rdoc)
76
68
 
77
69
  dataset.filter(:name => 'abc')
78
70
  dataset.filter('name = ?', 'abc')
71
+
79
72
  dataset.filter{|o| o.value > 100}
80
73
  dataset.exclude{|o| o.value <= 100}
81
74
 
@@ -83,13 +76,13 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
83
76
  dataset.where{|o| (o.value >= 50) & (o.value <= 100)}
84
77
 
85
78
  dataset.where('value IN ?', [50,75,100])
79
+ dataset.where(:value=>[50,75,100])
86
80
 
87
- # Get the first record that matches a condition
88
- dataset[:name => 'abc'] # Same as:
89
81
  dataset.filter(:name => 'abc').first
82
+ dataset[:name => 'abc'] # same as above
90
83
 
91
84
  # Filter using a subquery
92
- dataset.filter('price > ?', dataset.select('AVG(price) + 100'))
85
+ dataset.filter{|o| o.price > dataset.select(o.avg(price) + 100)}
93
86
 
94
87
  === Advanced filtering using ruby expressions
95
88
 
@@ -112,8 +105,8 @@ You can use arithmetic operators and specify SQL functions:
112
105
  DB[:items].filter((:x + :y) > :z).sql
113
106
  #=> "SELECT * FROM items WHERE ((x + y) > z)"
114
107
 
115
- DB[:items].filter{|o| :price - 100 < o.AVG(:price)}.sql
116
- #=> "SELECT * FROM items WHERE ((price - 100) < AVG(price))"
108
+ DB[:items].filter{|o| :price - 100 < o.avg(:price)}.sql
109
+ #=> "SELECT * FROM items WHERE ((price - 100) < avg(price))"
117
110
 
118
111
  == Ordering
119
112
 
@@ -126,16 +119,6 @@ You can use arithmetic operators and specify SQL functions:
126
119
  dataset.limit(30) # LIMIT 30
127
120
  dataset.limit(30, 10) # LIMIT 30 OFFSET 10
128
121
 
129
- == Pagination
130
-
131
- paginated = dataset.paginate(1, 10) # first page, 10 rows per page
132
- paginated.page_count #=> number of pages in dataset
133
- paginated.current_page #=> 1
134
- paginated.next_page #=> next page number or nil
135
- paginated.prev_page #=> previous page number or nil
136
- paginated.first_page? #=> true if page number = 1
137
- paginated.last_page? #=> true if page number = page_count
138
-
139
122
  == Joins
140
123
 
141
124
  DB[:items].left_outer_join(:categories, :id => :category_id).sql #=>
@@ -174,7 +157,7 @@ You can use arithmetic operators and specify SQL functions:
174
157
  DB.drop_table :items
175
158
 
176
159
  DB.create_table :test do
177
- String :zipcode, :size => 10
160
+ String :zipcode
178
161
  enum :system, :elements => ['mac', 'linux', 'windows']
179
162
  end
180
163
 
@@ -188,8 +171,8 @@ You can use arithmetic operators and specify SQL functions:
188
171
  == Transactions
189
172
 
190
173
  DB.transaction do
191
- dataset << {:first_name => 'Inigo', :last_name => 'Montoya'}
192
- dataset << {:first_name => 'Farm', :last_name => 'Boy'}
174
+ dataset.insert(:first_name => 'Inigo', :last_name => 'Montoya')
175
+ dataset.insert(:first_name => 'Farm', :last_name => 'Boy')
193
176
  end # Either both are inserted or neither are inserted
194
177
 
195
178
  Database#transaction is re-entrant:
@@ -206,10 +189,10 @@ Transactions are aborted if an error is raised:
206
189
  raise "some error occurred"
207
190
  end # ROLLBACK issued and the error is re-raised
208
191
 
209
- Transactions can also be aborted by raising Sequel::Error::Rollback:
192
+ Transactions can also be aborted by raising Sequel::Rollback:
210
193
 
211
194
  DB.transaction do
212
- raise(Sequel::Error::Rollback) if something_bad_happened
195
+ raise(Sequel::Rollback) if something_bad_happened
213
196
  end # ROLLBACK issued and no error raised
214
197
 
215
198
  Miscellaneous:
@@ -217,7 +200,7 @@ Miscellaneous:
217
200
  dataset.sql #=> "SELECT * FROM items"
218
201
  dataset.delete_sql #=> "DELETE FROM items"
219
202
  dataset.where(:name => 'sequel').exists #=> "EXISTS ( SELECT 1 FROM items WHERE name = 'sequel' )"
220
- dataset.print #=> pretty table print to $stdout
221
203
  dataset.columns #=> array of columns in the result set, does a SELECT
204
+
205
+ # Works on PostgreSQL, MySQL, SQLite, and JDBC
222
206
  DB.schema(:items) => [[:id, {:type=>:integer, ...}], [:name, {:type=>:string, ...}], ...]
223
- # Works on PostgreSQL, MySQL, SQLite, and JDBC