vizzuality-sequel-rails 0.3.4

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 (43) hide show
  1. data/.document +5 -0
  2. data/.gitignore +29 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +112 -0
  5. data/History.md +77 -0
  6. data/LICENSE +20 -0
  7. data/README.rdoc +102 -0
  8. data/Rakefile +9 -0
  9. data/autotest/discover.rb +1 -0
  10. data/lib/generators/sequel.rb +83 -0
  11. data/lib/generators/sequel/migration/migration_generator.rb +45 -0
  12. data/lib/generators/sequel/migration/templates/migration.rb +48 -0
  13. data/lib/generators/sequel/model/model_generator.rb +29 -0
  14. data/lib/generators/sequel/model/templates/migration.rb +16 -0
  15. data/lib/generators/sequel/model/templates/model.rb +6 -0
  16. data/lib/generators/sequel/observer/observer_generator.rb +19 -0
  17. data/lib/generators/sequel/observer/templates/observer.rb +7 -0
  18. data/lib/sequel-rails.rb +7 -0
  19. data/lib/sequel-rails/configuration.rb +63 -0
  20. data/lib/sequel-rails/migrations.rb +30 -0
  21. data/lib/sequel-rails/railtie.rb +93 -0
  22. data/lib/sequel-rails/railties/benchmarking_mixin.rb +23 -0
  23. data/lib/sequel-rails/railties/controller_runtime.rb +43 -0
  24. data/lib/sequel-rails/railties/database.rake +167 -0
  25. data/lib/sequel-rails/railties/i18n_support.rb +12 -0
  26. data/lib/sequel-rails/railties/log_subscriber.rb +31 -0
  27. data/lib/sequel-rails/runtime.rb +14 -0
  28. data/lib/sequel-rails/session_store.rb +82 -0
  29. data/lib/sequel-rails/setup.rb +27 -0
  30. data/lib/sequel-rails/storage.rb +222 -0
  31. data/lib/sequel-rails/version.rb +5 -0
  32. data/lib/sequel/plugins/rails_extensions.rb +35 -0
  33. data/spec/rcov.opts +6 -0
  34. data/spec/spec.opts +4 -0
  35. data/spec/spec_helper.rb +7 -0
  36. data/tasks/ci.rake +1 -0
  37. data/tasks/clean.rake +6 -0
  38. data/tasks/metrics.rake +37 -0
  39. data/tasks/spec.rake +30 -0
  40. data/tasks/yard.rake +9 -0
  41. data/tasks/yardstick.rake +20 -0
  42. data/vizzuality-sequel-rails.gemspec +29 -0
  43. metadata +208 -0
@@ -0,0 +1,167 @@
1
+ # TODO: DRY these up
2
+ namespace :db do
3
+ namespace :schema do
4
+ desc "Create a db/schema.rb file that can be portably used against any DB supported by Sequel"
5
+ task :dump => :environment do
6
+ Sequel.extension :schema_dumper
7
+ db = Sequel.connect(::Rails::Sequel.configuration.environment_for(Rails.env))
8
+ File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", "w") do |file|
9
+ file.write db.dump_schema_migration(same_db: true)
10
+ end
11
+ Rake::Task["db:schema:dump"].reenable
12
+ end
13
+
14
+ desc "Load a schema.rb file into the database"
15
+ task :load => :environment do
16
+ require 'sequel-rails/storage'
17
+ Rails::Sequel::Storage.new(Rails.env).create
18
+
19
+ file = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb"
20
+ if File.exists?(file)
21
+ load(file)
22
+ else
23
+ abort %{#{file} doesn't exist yet. Run "rake db:migrate" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/boot.rb to limit the frameworks that will be loaded}
24
+ end
25
+ end
26
+ end
27
+
28
+ namespace :create do
29
+ desc 'Create all the local databases defined in config/database.yml'
30
+ task :all => :environment do
31
+ require 'sequel-rails/storage'
32
+ Rails::Sequel::Storage.create_all
33
+ end
34
+ end
35
+
36
+ desc "Create the database defined in config/database.yml for the current Rails.env - also creates the test database if Rails.env.development?"
37
+ task :create, [:env] => :environment do |t, args|
38
+ args.with_defaults(:env => Rails.env)
39
+
40
+ require 'sequel-rails/storage'
41
+ Rails::Sequel::Storage.new(args.env).create
42
+
43
+ if Rails.env.development? && Rails.configuration.database_configuration['test']
44
+ Rails::Sequel::Storage.new('test').create
45
+ end
46
+ end
47
+
48
+ namespace :drop do
49
+ desc 'Drops all the local databases defined in config/database.yml'
50
+ task :all => :environment do
51
+ require 'sequel-rails/storage'
52
+ Rails::Sequel::Storage.drop_all
53
+ end
54
+ end
55
+
56
+ desc "Create the database defined in config/database.yml for the current Rails.env - also creates the test database if Rails.env.development?"
57
+ task :drop, [:env] => :environment do |t, args|
58
+ args.with_defaults(:env => Rails.env)
59
+
60
+ require 'sequel-rails/storage'
61
+ Rails::Sequel::Storage.new(args.env).drop
62
+
63
+ if Rails.env.development? && Rails.configuration.database_configuration['test']
64
+ Rails::Sequel::Storage.new('test').drop
65
+ end
66
+ end
67
+
68
+ namespace :migrate do
69
+ task :load => :environment do
70
+ require 'sequel-rails/migrations'
71
+ end
72
+
73
+ desc 'Rollbacks the database one migration and re migrate up. If you want to rollback more than one step, define STEP=x. Target specific version with VERSION=x.'
74
+ task :redo => :load do
75
+ if ENV["VERSION"]
76
+ Rake::Task["db:migrate:down"].invoke
77
+ Rake::Task["db:migrate:up"].invoke
78
+ else
79
+ Rake::Task["db:rollback"].invoke
80
+ Rake::Task["db:migrate"].invoke
81
+ end
82
+ end
83
+
84
+
85
+ desc 'Resets your database using your migrations for the current environment'
86
+ task :reset => ["db:drop", "db:create", "db:migrate"]
87
+
88
+ desc 'Runs the "up" for a given migration VERSION.'
89
+ task :up => :load do
90
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
91
+ raise "VERSION is required" unless version
92
+ Rails::Sequel::Migrations.migrate_up!(version)
93
+ Rake::Task["db:schema:dump"].invoke if Rails.env != 'test'
94
+ end
95
+
96
+ desc 'Runs the "down" for a given migration VERSION.'
97
+ task :down => :load do
98
+ version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
99
+ raise "VERSION is required" unless version
100
+ Rails::Sequel::Migrations.migrate_down!(version)
101
+ Rake::Task["db:schema:dump"].invoke if Rails.env != 'test'
102
+ end
103
+ end
104
+
105
+ desc 'Migrate the database to the latest version'
106
+ task :migrate => :'migrate:load' do
107
+ Rails::Sequel::Migrations.migrate_up!(ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
108
+ Rake::Task["db:schema:dump"].invoke if Rails.env != 'test'
109
+ end
110
+
111
+ desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n'
112
+ task :rollback => :'migrate:load' do
113
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
114
+ Sequel::Migrator.rollback('db/migrate/', step)
115
+ Rake::Task["db:schema:dump"].invoke if Rails.env != 'test'
116
+ end
117
+
118
+ desc 'Pushes the schema to the next version. Specify the number of steps with STEP=n'
119
+ task :forward => :'migrate:load' do
120
+ step = ENV['STEP'] ? ENV['STEP'].to_i : 1
121
+ Sequel::Migrator.forward('db/migrate/', step)
122
+ Rake::Task["db:schema:dump"].invoke if Rails.env != 'test'
123
+ end
124
+
125
+ desc 'Load the seed data from db/seeds.rb'
126
+ task :seed => :environment do
127
+ seed_file = File.join(Rails.root, 'db', 'seeds.rb')
128
+ load(seed_file) if File.exist?(seed_file)
129
+ end
130
+
131
+ desc 'Create the database, load the schema, and initialize with the seed data'
132
+ task :setup => [ 'db:create', 'db:migrate', 'db:seed' ]
133
+
134
+ desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
135
+ task :reset => [ 'db:drop', 'db:setup' ]
136
+
137
+ desc 'Forcibly close any open connections to the test database'
138
+ task :force_close_open_connections => :environment do
139
+ if Rails.env.test?
140
+ db_config = Rails.configuration.database_configuration[Rails.env].symbolize_keys
141
+ begin
142
+ #Will only work on Postgres > 8.4
143
+ Sequel::Model.db.execute <<-SQL.gsub(/^\s{9}/,'')
144
+ SELECT COUNT(pg_terminate_backend(procpid))
145
+ FROM pg_stat_activity
146
+ WHERE datname = '#{db_config[:database]}';
147
+ SQL
148
+ rescue => e
149
+ #Will raise an error as it kills existing process running this command
150
+ #Seems to be only way to ensure *all* test connections are closed
151
+ end
152
+ end
153
+ end
154
+
155
+ namespace :test do
156
+ task :prepare do
157
+ Rails.env = 'test'
158
+ Rake::Task['db:force_close_open_connections'].invoke()
159
+ Rake::Task['db:reset'].invoke()
160
+ Sequel::DATABASES.each do |db|
161
+ db.disconnect
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ task 'test:prepare' => 'db:test:prepare'
@@ -0,0 +1,12 @@
1
+ module Rails
2
+ module Sequel
3
+
4
+ module I18nSupport
5
+ # Set the i18n scope to overwrite ActiveModel.
6
+ def i18n_scope #:nodoc:
7
+ :sequel
8
+ end
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ module Sequel
2
+ module Railties
3
+
4
+ class LogSubscriber < ActiveSupport::LogSubscriber
5
+
6
+ def sql(event)
7
+ name = '%s (%.1fms)' % [event.payload[:name], event.duration]
8
+ sql = event.payload[:sql].squeeze(' ')
9
+
10
+ if odd?
11
+ name = color(name, :cyan, true)
12
+ sql = color(sql, nil, true)
13
+ else
14
+ name = color(name, :magenta, true)
15
+ end
16
+
17
+ debug " #{name} #{sql}"
18
+ end
19
+
20
+ def odd?
21
+ @odd_or_even = !@odd_or_even
22
+ end
23
+
24
+ def logger
25
+ ::Rails::Sequel.configuration.logger
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ module Rails
2
+ module Sequel
3
+
4
+ class << self
5
+ def reset_runtime
6
+ @runtime ||= 0
7
+
8
+ rt, @runtime = @runtime, 0
9
+ rt
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,82 @@
1
+ require 'sequel'
2
+
3
+ # Implements Sequel-specific session store.
4
+
5
+ module Rails
6
+ module Sequel
7
+
8
+ class SessionStore < ActionDispatch::Session::AbstractStore
9
+
10
+ class Session < ::Sequel::Model
11
+
12
+ # property :id, Serial
13
+ # property :session_id, String, :required => true, :unique => true, :unique_index => true
14
+ # property :data, Object, :required => true, :default => ActiveSupport::Base64.encode64(Marshal.dump({}))
15
+ # property :updated_at, DateTime, :required => false, :index => true
16
+
17
+ class << self
18
+
19
+ def auto_migrate!
20
+ self.db.create_table :sessions do
21
+ primary_key :id
22
+ column :session_id, String,
23
+ :null => false,
24
+ :unique => true,
25
+ :index => true
26
+
27
+ column :data, :text,
28
+ :null => false
29
+
30
+ column :updated_at, DateTime,
31
+ :null => true,
32
+ :index => true
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ def self.name
39
+ 'session'
40
+ end
41
+
42
+ end
43
+
44
+ SESSION_RECORD_KEY = 'rack.session.record'.freeze
45
+
46
+ cattr_accessor :session_class
47
+ self.session_class = Session
48
+
49
+ private
50
+
51
+ def get_session(env, sid)
52
+ sid ||= generate_sid
53
+ session = find_session(sid)
54
+ env[SESSION_RECORD_KEY] = session
55
+ [ sid, session.data ]
56
+ end
57
+
58
+ def set_session(env, sid, session_data)
59
+ session = get_session_resource(env, sid)
60
+ session.data = session_data
61
+ session.updated_at = Time.now if session.dirty?
62
+ session.save
63
+ end
64
+
65
+ def get_session_resource(env, sid)
66
+ if env[ENV_SESSION_OPTIONS_KEY][:id].nil?
67
+ env[SESSION_RECORD_KEY] = find_session(sid)
68
+ else
69
+ env[SESSION_RECORD_KEY] ||= find_session(sid)
70
+ end
71
+ end
72
+
73
+ def find_session(sid)
74
+ klass = self.class.session_class
75
+
76
+ klass.where(:session_id => sid).first || klass.new(:session_id => sid)
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,27 @@
1
+ require 'active_support/core_ext/hash/except'
2
+
3
+ require 'sequel/extensions/migration'
4
+
5
+ require 'sequel-rails/configuration'
6
+ require 'sequel-rails/runtime'
7
+ require 'sequel-rails/railties/benchmarking_mixin'
8
+
9
+ module Rails
10
+ module Sequel
11
+
12
+ def self.connection(environment = nil)
13
+ environment ||= Rails.env
14
+ @@connections[environment] ||= setup(environment)
15
+ end
16
+
17
+ def self.setup(environment = nil)
18
+ environment ||= Rails.env
19
+ puts "[sequel-blat] Setting up the #{environment.inspect} environment:"
20
+
21
+ @@connections ||= {}
22
+ @@connections[environment] ||= ::Sequel.connect({:logger => configuration.logger}.merge(::Rails::Sequel.configuration.environment_for(environment.to_s)))
23
+ @@connections[environment]
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,222 @@
1
+ module Rails
2
+ module Sequel
3
+
4
+ def self.storage
5
+ Storage
6
+ end
7
+
8
+ class Storage
9
+ attr_reader :config
10
+
11
+ def self.create_all
12
+ with_local_repositories { |config| create_environment(config) }
13
+ end
14
+
15
+ def self.drop_all
16
+ with_local_repositories { |config| drop_environment(config) }
17
+ end
18
+
19
+ def self.create_environment(config)
20
+ new(config).create
21
+ end
22
+
23
+ def self.drop_environment(config)
24
+ new(config).drop
25
+ end
26
+
27
+ def self.new(config)
28
+ config = Rails::Sequel.configuration.environments[config.to_s] unless config.kind_of?(Hash)
29
+
30
+ klass = lookup_class(config['adapter'])
31
+ if klass.equal?(self)
32
+ super(config)
33
+ else
34
+ klass.new(config)
35
+ end
36
+ end
37
+
38
+ class << self
39
+ private
40
+
41
+ def with_local_repositories
42
+ Rails::Sequel.configuration.environments.each_value do |config|
43
+ next if config['database'].blank?
44
+ if config['host'].blank? || %w[ 127.0.0.1 localhost ].include?(config['host'])
45
+ yield(config)
46
+ else
47
+ puts "This task only modifies local databases. #{config['database']} is on a remote host."
48
+ end
49
+ end
50
+ end
51
+
52
+ def lookup_class(adapter)
53
+ klass_name = adapter.camelize.to_sym
54
+
55
+ unless Storage.const_defined?(klass_name)
56
+ raise "Adapter #{adapter} not supported (#{klass_name.inspect})"
57
+ end
58
+
59
+ const_get(klass_name)
60
+ end
61
+
62
+ end
63
+
64
+ def initialize(config)
65
+ @config = config
66
+ end
67
+
68
+ def create
69
+ _create
70
+ puts "[sequel] Created database '#{database}'"
71
+ end
72
+
73
+ def drop
74
+ ::Sequel::Model.db.disconnect
75
+ _drop
76
+ puts "[sequel] Dropped database '#{database}'"
77
+ end
78
+
79
+ def database
80
+ @database ||= config['database'] || config['path']
81
+ end
82
+
83
+ def username
84
+ @username ||= config['username'] || config['user'] || ''
85
+ end
86
+
87
+ def password
88
+ @password ||= config['password'] || ''
89
+ end
90
+
91
+ def host
92
+ @host ||= config['host'] || ''
93
+ end
94
+
95
+ def port
96
+ @port ||= config['port'] || ''
97
+ end
98
+
99
+ def owner
100
+ @owner ||= config['owner'] || ''
101
+ end
102
+
103
+ def charset
104
+ @charset ||= config['charset'] || ENV['CHARSET'] || 'utf8'
105
+ end
106
+
107
+ class Sqlite < Storage
108
+ def _create
109
+ return if in_memory?
110
+ ::Sequel.connect(config.merge('database' => path))
111
+ end
112
+
113
+ def _drop
114
+ return if in_memory?
115
+ path.unlink if path.file?
116
+ end
117
+
118
+ private
119
+
120
+ def in_memory?
121
+ database == ':memory:'
122
+ end
123
+
124
+ def path
125
+ @path ||= Pathname(File.expand_path(database, Rails.root))
126
+ end
127
+
128
+ end
129
+
130
+ class Mysql < Storage
131
+ def _create
132
+ execute("CREATE DATABASE IF NOT EXISTS `#{database}` DEFAULT CHARACTER SET #{charset} DEFAULT COLLATE #{collation}")
133
+ end
134
+
135
+ def _drop
136
+ execute("DROP DATABASE IF EXISTS `#{database}`")
137
+ end
138
+
139
+ private
140
+
141
+ def execute(statement)
142
+ commands = ["mysql"]
143
+ commands << "--user" << username unless username.blank?
144
+ commands << "--password" << password unless password.blank?
145
+ commands << "--host" << host unless host.blank?
146
+ commands << "-e" << statement
147
+ system(*commands)
148
+ end
149
+
150
+ def collation
151
+ @collation ||= config['collation'] || ENV['COLLATION'] || 'utf8_unicode_ci'
152
+ end
153
+
154
+ end
155
+ class Mysql2 < Mysql
156
+ end
157
+
158
+ class Postgres < Storage
159
+ def _create
160
+ ENV["PGPASSWORD"] = password unless password.blank?
161
+ commands = ["createdb", "--encoding", charset]
162
+ commands << "--username" << username unless username.blank?
163
+ commands << "--owner" << owner unless owner.blank?
164
+ commands << "--port" << port.to_s unless port.blank?
165
+ commands << "--host" << host unless host.blank?
166
+ commands << database
167
+ res = system(*commands)
168
+ ENV["PGPASSWORD"] = nil
169
+ res
170
+ end
171
+
172
+ def _drop
173
+ system("dropdb", "-U", username, database)
174
+ end
175
+ end
176
+
177
+ class Jdbc < Storage
178
+
179
+ def _is_mysql?
180
+ database.match(/^jdbc:mysql/)
181
+ end
182
+
183
+ def _root_url
184
+ database.scan /^jdbc:mysql:\/\/\w*:?\d*/
185
+ end
186
+
187
+ def db_name
188
+ database.scan(/^jdbc:mysql:\/\/\w+:?\d*\/(\w+)/).flatten.first
189
+ end
190
+
191
+ def _params
192
+ database.scan /\?.*$/
193
+ end
194
+
195
+ def _create
196
+ if _is_mysql?
197
+ ::Sequel.connect("#{_root_url}#{_params}") do |db|
198
+ db.execute("CREATE DATABASE IF NOT EXISTS `#{db_name}` DEFAULT CHARACTER SET #{charset} DEFAULT COLLATE #{collation}")
199
+ end
200
+ end
201
+ end
202
+
203
+ def _drop
204
+ if _is_mysql?
205
+ ::Sequel.connect("#{_root_url}#{_params}") do |db|
206
+ db.execute("DROP DATABASE IF EXISTS `#{db_name}`")
207
+ end
208
+ end
209
+ end
210
+
211
+ private
212
+
213
+ def collation
214
+ @collation ||= config['collation'] || ENV['COLLATION'] || 'utf8_unicode_ci'
215
+ end
216
+
217
+
218
+ end
219
+
220
+ end
221
+ end
222
+ end