vizzuality-sequel-rails 0.3.4

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