sequel-rails 0.1.8 → 0.4.0.pre

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 (74) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +12 -0
  4. data/Gemfile +13 -16
  5. data/History.md +142 -0
  6. data/README.md +124 -0
  7. data/Rakefile +6 -30
  8. data/config.ru +7 -0
  9. data/lib/generators/sequel.rb +11 -8
  10. data/lib/generators/sequel/migration/migration_generator.rb +36 -11
  11. data/lib/generators/sequel/migration/templates/migration.rb.erb +48 -0
  12. data/lib/generators/sequel/model/model_generator.rb +8 -2
  13. data/lib/generators/sequel/model/templates/migration.rb.erb +16 -0
  14. data/lib/generators/sequel/model/templates/{model.rb → model.rb.erb} +4 -1
  15. data/lib/generators/sequel/observer/observer_generator.rb +2 -2
  16. data/lib/generators/sequel/observer/templates/{observer.rb → observer.rb.erb} +0 -0
  17. data/lib/sequel-rails.rb +1 -1
  18. data/lib/sequel_rails.rb +2 -0
  19. data/lib/sequel_rails/configuration.rb +64 -0
  20. data/lib/sequel_rails/migrations.rb +22 -0
  21. data/lib/sequel_rails/railtie.rb +94 -0
  22. data/lib/sequel_rails/railties/controller_runtime.rb +40 -0
  23. data/lib/sequel_rails/railties/database.rake +175 -0
  24. data/lib/sequel_rails/railties/i18n_support.rb +10 -0
  25. data/lib/sequel_rails/railties/log_subscriber.rb +56 -0
  26. data/lib/sequel_rails/sequel/database/active_support_notification.rb +28 -0
  27. data/lib/sequel_rails/sequel/plugins/rails_extensions.rb +35 -0
  28. data/lib/sequel_rails/session_store.rb +80 -0
  29. data/lib/sequel_rails/storage.rb +58 -0
  30. data/lib/sequel_rails/storage/abstract.rb +52 -0
  31. data/lib/sequel_rails/storage/jdbc.rb +45 -0
  32. data/lib/sequel_rails/storage/mysql.rb +31 -0
  33. data/lib/sequel_rails/storage/mysql2.rb +6 -0
  34. data/lib/sequel_rails/storage/postgres.rb +22 -0
  35. data/lib/sequel_rails/storage/sqlite.rb +26 -0
  36. data/lib/sequel_rails/version.rb +3 -0
  37. data/sequel-rails.gemspec +22 -86
  38. data/spec/internal/app/models/user.rb +2 -0
  39. data/spec/internal/config/database.yml +7 -0
  40. data/spec/internal/config/routes.rb +3 -0
  41. data/spec/internal/db/schema.rb +8 -0
  42. data/spec/internal/public/favicon.ico +0 -0
  43. data/spec/lib/generators/sequel/migration_spec.rb +256 -0
  44. data/spec/lib/sequel_rails/railtie_spec.rb +85 -0
  45. data/spec/lib/sequel_rails/railties/log_subscriber_spec.rb +29 -0
  46. data/spec/lib/sequel_rails/storage_spec.rb +108 -0
  47. data/spec/spec_helper.rb +30 -16
  48. data/tasks/spec.rake +63 -29
  49. metadata +194 -142
  50. data/CHANGELOG +0 -15
  51. data/README.rdoc +0 -86
  52. data/VERSION +0 -1
  53. data/autotest/discover.rb +0 -1
  54. data/lib/generators/sequel/migration/templates/migration.rb +0 -16
  55. data/lib/sequel-rails/configuration.rb +0 -61
  56. data/lib/sequel-rails/migrations.rb +0 -30
  57. data/lib/sequel-rails/railtie.rb +0 -90
  58. data/lib/sequel-rails/railties/benchmarking_mixin.rb +0 -23
  59. data/lib/sequel-rails/railties/controller_runtime.rb +0 -43
  60. data/lib/sequel-rails/railties/database.rake +0 -148
  61. data/lib/sequel-rails/railties/i18n_support.rb +0 -12
  62. data/lib/sequel-rails/railties/log_subscriber.rb +0 -31
  63. data/lib/sequel-rails/runtime.rb +0 -14
  64. data/lib/sequel-rails/session_store.rb +0 -82
  65. data/lib/sequel-rails/setup.rb +0 -19
  66. data/lib/sequel-rails/storage.rb +0 -210
  67. data/spec/rcov.opts +0 -6
  68. data/spec/setup_spec.rb +0 -7
  69. data/spec/spec.opts +0 -4
  70. data/tasks/ci.rake +0 -1
  71. data/tasks/clean.rake +0 -6
  72. data/tasks/metrics.rake +0 -37
  73. data/tasks/yard.rake +0 -9
  74. data/tasks/yardstick.rake +0 -20
@@ -0,0 +1,10 @@
1
+ module SequelRails
2
+
3
+ module I18nSupport
4
+ # Set the i18n scope to overwrite ActiveModel.
5
+ def i18n_scope #:nodoc:
6
+ :sequel
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,56 @@
1
+ module SequelRails
2
+ module Railties
3
+
4
+ class LogSubscriber < ActiveSupport::LogSubscriber
5
+
6
+ def self.runtime=(value)
7
+ Thread.current["sequel_sql_runtime"] = value
8
+ end
9
+
10
+ def self.runtime
11
+ Thread.current["sequel_sql_runtime"] ||= 0
12
+ end
13
+
14
+ def self.reset_runtime
15
+ rt, self.runtime = runtime, 0
16
+ rt
17
+ end
18
+
19
+ def sql(event)
20
+ self.class.runtime += event.duration
21
+ return unless logger.debug?
22
+
23
+ payload = event.payload
24
+
25
+ name = '%s (%.1fms)' % [payload[:name], event.duration]
26
+ sql = payload[:sql].squeeze(' ')
27
+ binds = nil
28
+
29
+ unless (payload[:binds] || []).empty?
30
+ binds = " " + payload[:binds].map { |col,v|
31
+ [col.name, v]
32
+ }.inspect
33
+ end
34
+
35
+ if odd?
36
+ name = color(name, :cyan, true)
37
+ sql = color(sql, nil, true)
38
+ else
39
+ name = color(name, :magenta, true)
40
+ end
41
+
42
+ debug " #{name} #{sql}#{binds}"
43
+ end
44
+
45
+ def odd?
46
+ @odd_or_even = !@odd_or_even
47
+ end
48
+
49
+ def logger
50
+ ::SequelRails.configuration.logger
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,28 @@
1
+ require "sequel/database/logging"
2
+ require "active_support/notifications"
3
+
4
+ module Sequel
5
+ class Database
6
+
7
+ def log_yield(sql, args=nil)
8
+ sql_for_log = args ? "#{sql}; #{args.inspect}" : sql
9
+ start = Time.now
10
+ begin
11
+ ::ActiveSupport::Notifications.instrument(
12
+ "sql.sequel",
13
+ sql: sql,
14
+ name: self.class,
15
+ binds: args,
16
+ ) do
17
+ yield
18
+ end
19
+ rescue => e
20
+ log_exception(e, sql_for_log) unless @loggers.empty?
21
+ raise
22
+ ensure
23
+ log_duration(Time.now - start, sql_for_log) unless e || @loggers.empty?
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,35 @@
1
+ require "sequel"
2
+
3
+ module Sequel
4
+ module Plugins
5
+ # The RailsExtensions plugin adds a single class method to Sequel::Model in
6
+ # order to make its use in controllers a little more like ActiveRecord's.
7
+ # The +find!+ method is added which will raise an exception if no object is
8
+ # found. By adding the following code to a Railtie:
9
+ #
10
+ # config.action_dispatch.rescue_responses.merge!(
11
+ # 'Sequel::Plugins::RailsExtensions::ModelNotFound' => :not_found
12
+ # )
13
+ #
14
+ # Usage:
15
+ #
16
+ # # Apply plugin to all models:
17
+ # Sequel::Model.plugin :rails_extensions
18
+ #
19
+ # # Apply plugin to a single model:
20
+ # Album.plugin :rails_extensions
21
+ module RailsExtensions
22
+ class ModelNotFound < Sequel::Error
23
+ end
24
+
25
+ module ClassMethods
26
+ def find!(args)
27
+ m = self[args]
28
+ raise ModelNotFound, "Couldn't find #{self} matching #{args}." unless m
29
+ m
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,80 @@
1
+ require "sequel"
2
+
3
+ # Implements Sequel-specific session store.
4
+
5
+ module SequelRails
6
+
7
+ class SessionStore < ActionDispatch::Session::AbstractStore
8
+
9
+ class Session < ::Sequel::Model
10
+
11
+ # property :id, Serial
12
+ # property :session_id, String, :required => true, :unique => true, :unique_index => true
13
+ # property :data, Object, :required => true, :default => ActiveSupport::Base64.encode64(Marshal.dump({}))
14
+ # property :updated_at, DateTime, :required => false, :index => true
15
+
16
+ class << self
17
+
18
+ def auto_migrate!
19
+ self.db.create_table :sessions do
20
+ primary_key :id
21
+ column :session_id, String,
22
+ :null => false,
23
+ :unique => true,
24
+ :index => true
25
+
26
+ column :data, :text,
27
+ :null => false
28
+
29
+ column :updated_at, DateTime,
30
+ :null => true,
31
+ :index => true
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ def self.name
38
+ 'session'
39
+ end
40
+
41
+ end
42
+
43
+ SESSION_RECORD_KEY = 'rack.session.record'.freeze
44
+
45
+ cattr_accessor :session_class
46
+ self.session_class = Session
47
+
48
+ private
49
+
50
+ def get_session(env, sid)
51
+ sid ||= generate_sid
52
+ session = find_session(sid)
53
+ env[SESSION_RECORD_KEY] = session
54
+ [ sid, session.data ]
55
+ end
56
+
57
+ def set_session(env, sid, session_data)
58
+ session = get_session_resource(env, sid)
59
+ session.data = session_data
60
+ session.updated_at = Time.now if session.dirty?
61
+ session.save
62
+ end
63
+
64
+ def get_session_resource(env, sid)
65
+ if env[ENV_SESSION_OPTIONS_KEY][:id].nil?
66
+ env[SESSION_RECORD_KEY] = find_session(sid)
67
+ else
68
+ env[SESSION_RECORD_KEY] ||= find_session(sid)
69
+ end
70
+ end
71
+
72
+ def find_session(sid)
73
+ klass = self.class.session_class
74
+
75
+ klass.where(:session_id => sid).first || klass.new(:session_id => sid)
76
+ end
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,58 @@
1
+ require "sequel_rails/storage/abstract"
2
+ require "sequel_rails/storage/sqlite"
3
+ require "sequel_rails/storage/mysql"
4
+ require "sequel_rails/storage/mysql2"
5
+ require "sequel_rails/storage/postgres"
6
+ require "sequel_rails/storage/jdbc"
7
+
8
+ module SequelRails
9
+ module Storage
10
+ def self.create_all
11
+ with_local_repositories { |config| create_environment(config) }
12
+ end
13
+
14
+ def self.drop_all
15
+ with_local_repositories { |config| drop_environment(config) }
16
+ end
17
+
18
+ def self.create_environment(config)
19
+ adapter_for(config).create
20
+ end
21
+
22
+ def self.drop_environment(config)
23
+ adapter_for(config).drop
24
+ end
25
+
26
+ def self.adapter_for(config_or_env)
27
+ config = if config_or_env.kind_of? Hash
28
+ config_or_env
29
+ else
30
+ ::SequelRails.configuration.environments[config_or_env.to_s]
31
+ end
32
+ lookup_class(config['adapter']).new config
33
+ end
34
+
35
+ private
36
+
37
+ def self.with_local_repositories
38
+ ::SequelRails.configuration.environments.each_value do |config|
39
+ next if config['database'].blank?
40
+ if config['host'].blank? || %w[ 127.0.0.1 localhost ].include?(config['host'])
41
+ yield config
42
+ else
43
+ puts "This task only modifies local databases. #{config['database']} is on a remote host."
44
+ end
45
+ end
46
+ end
47
+
48
+ def self.lookup_class(adapter)
49
+ klass_name = adapter.camelize.to_sym
50
+
51
+ unless self.const_defined?(klass_name)
52
+ raise "Adapter #{adapter} not supported (#{klass_name.inspect})"
53
+ end
54
+
55
+ const_get klass_name
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,52 @@
1
+ module SequelRails
2
+ module Storage
3
+ class Abstract
4
+
5
+ attr_reader :config
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def create
12
+ _create
13
+ puts "[sequel] Created database '#{database}'"
14
+ end
15
+
16
+ def drop
17
+ ::Sequel::Model.db.disconnect
18
+ _drop
19
+ puts "[sequel] Dropped database '#{database}'"
20
+ end
21
+
22
+ def database
23
+ @database ||= config['database'] || config['path']
24
+ end
25
+
26
+ def username
27
+ @username ||= config['username'] || config['user'] || ''
28
+ end
29
+
30
+ def password
31
+ @password ||= config['password'] || ''
32
+ end
33
+
34
+ def host
35
+ @host ||= config['host'] || ''
36
+ end
37
+
38
+ def port
39
+ @port ||= config['port'] || ''
40
+ end
41
+
42
+ def owner
43
+ @owner ||= config['owner'] || ''
44
+ end
45
+
46
+ def charset
47
+ @charset ||= config['charset'] || ENV['CHARSET'] || 'utf8'
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,45 @@
1
+ module SequelRails
2
+ module Storage
3
+ class Jdbc < Abstract
4
+
5
+ def _is_mysql?
6
+ database.match(/^jdbc:mysql/)
7
+ end
8
+
9
+ def _root_url
10
+ database.scan(/^jdbc:mysql:\/\/\w*:?\d*/)
11
+ end
12
+
13
+ def db_name
14
+ database.scan(/^jdbc:mysql:\/\/\w+:?\d*\/(\w+)/).flatten.first
15
+ end
16
+
17
+ def _params
18
+ database.scan(/\?.*$/)
19
+ end
20
+
21
+ def _create
22
+ if _is_mysql?
23
+ ::Sequel.connect("#{_root_url}#{_params}") do |db|
24
+ db.execute("CREATE DATABASE IF NOT EXISTS `#{db_name}` DEFAULT CHARACTER SET #{charset} DEFAULT COLLATE #{collation}")
25
+ end
26
+ end
27
+ end
28
+
29
+ def _drop
30
+ if _is_mysql?
31
+ ::Sequel.connect("#{_root_url}#{_params}") do |db|
32
+ db.execute("DROP DATABASE IF EXISTS `#{db_name}`")
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def collation
40
+ @collation ||= config['collation'] || ENV['COLLATION'] || 'utf8_unicode_ci'
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,31 @@
1
+ require 'shellwords'
2
+
3
+ module SequelRails
4
+ module Storage
5
+ class Mysql < Abstract
6
+ def _create
7
+ execute("CREATE DATABASE IF NOT EXISTS `#{database}` DEFAULT CHARACTER SET #{charset} DEFAULT COLLATE #{collation}")
8
+ end
9
+
10
+ def _drop
11
+ execute("DROP DATABASE IF EXISTS `#{database}`")
12
+ end
13
+
14
+ private
15
+
16
+ def execute(statement)
17
+ commands = ["mysql"]
18
+ commands << "--user=#{Shellwords.escape(username)}" unless username.blank?
19
+ commands << "--password=#{Shellwords.escape(password)}" unless password.blank?
20
+ commands << "--host=#{host}" unless host.blank?
21
+ commands << "-e" << statement
22
+ system(*commands)
23
+ end
24
+
25
+ def collation
26
+ @collation ||= config['collation'] || ENV['COLLATION'] || 'utf8_unicode_ci'
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,6 @@
1
+ module SequelRails
2
+ module Storage
3
+ class Mysql2 < Mysql
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,22 @@
1
+ module SequelRails
2
+ module Storage
3
+ class Postgres < Abstract
4
+ def _create
5
+ ENV["PGPASSWORD"] = password unless password.blank?
6
+ commands = ["createdb", "--encoding", charset]
7
+ commands << "--username" << username unless username.blank?
8
+ commands << "--owner" << owner unless owner.blank?
9
+ commands << "--port" << port unless port.blank?
10
+ commands << "--host" << host unless host.blank?
11
+ commands << database
12
+ res = system(*commands)
13
+ ENV["PGPASSWORD"] = nil
14
+ res
15
+ end
16
+
17
+ def _drop
18
+ system("dropdb", "-U", username, database)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ module SequelRails
2
+ module Storage
3
+ class Sqlite < Abstract
4
+ def _create
5
+ return if in_memory?
6
+ ::Sequel.connect(config.merge('database' => path))
7
+ end
8
+
9
+ def _drop
10
+ return if in_memory?
11
+ path.unlink if path.file?
12
+ end
13
+
14
+ private
15
+
16
+ def in_memory?
17
+ database == ':memory:'
18
+ end
19
+
20
+ def path
21
+ @path ||= Pathname(File.expand_path(database, Rails.root))
22
+ end
23
+
24
+ end
25
+ end
26
+ end