communard 0.0.5 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 803308ca6f5424ff74123dcbb892f6ef6b76ecd0
4
- data.tar.gz: 310a953d2846d2f7f0b7f0188ae69c84635260d9
2
+ SHA256:
3
+ metadata.gz: 94f9d91890f50281fc8ce1d4678153cf2aff2c2068c00166774aeeafe80dfb16
4
+ data.tar.gz: cd21196d14631a2e3eda1435e16c4fd4afdabc1da2ab16d0d198290c1275e153
5
5
  SHA512:
6
- metadata.gz: bcd25b010ae79cc52aa3c50cea57d74072d924f68b3d84873d7399396052305d67beacf728d920e788ea7c0ca11bcd870cb6d036b5994938dc28e3eaa85f0f3d
7
- data.tar.gz: e5c9d2270735b60a121e5057215f7d359268472398e16f4101bd605c09bb509f64162d9f1cedfaba4fe216be5f9b6b37befe056383a9148925287b5e66ca7223
6
+ metadata.gz: 4968eb2fb22782695eb7335028f0d8fb76d58a3bb4fe437ec3e3da75fb8b1edc74cc66a8b2fceeabbad8c6c44aa7adf8c206566ba08fed93552ec8fe356521ae
7
+ data.tar.gz: 55000cbc291e4ca20050c1fff461b709f689aeea3a17f28d922ec8c69220d042dbd22ff628f5be8ce2889594ab9c0d8fa652ac82b9b60c6113d16d3e278e7101
data/README.md CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  Communard adds some conventions from [ActiveRecord][ar] to [Sequel][sq].
4
4
 
5
- This means you can use `config/database.yml` and `db/migrate` again, so you
6
- don't have to change deployment scripts that are made for ActiveRecord.
7
-
8
5
  Sequel doesn't provide the exact same functionality as ActiveRecord. Communard
9
6
  doesn't try to make Sequel quack like ActiveRecord, it just tries to help with
10
7
  some (not all) setup.
@@ -31,25 +28,15 @@ $ gem install communard
31
28
 
32
29
  ## Usage
33
30
 
34
- ### Connecting to the database
35
-
36
- To get a database connection:
37
-
38
- ``` ruby
39
- DB = Communard.connect
40
- ```
41
-
42
- The `DB` object will be familiar to you if you've ever read the Sequel documentation.
43
-
44
- Note: Communard doesn't remember your connection.
45
-
46
31
  ### Rake integration
47
32
 
48
33
  To add most Rake tasks, add this to your `Rakefile` or to `lib/tasks/communard.rake`:
49
34
 
50
35
  ``` ruby
51
36
  require "communard/rake"
52
- Communard::Rake.add_tasks
37
+ namespace :db do
38
+ Communard::Rake.add_tasks
39
+ end
53
40
  ```
54
41
 
55
42
  This will add the most used rake tasks, like `db:create`, `db:migrate`, and `db:setup`.
@@ -60,34 +47,68 @@ To see them all:
60
47
  $ rake -T db
61
48
  ```
62
49
 
50
+ `Communard::Rake.add_tasks` accepts the same configuration options as
51
+ `Sequel.connect`. It doesn't immediately make a connection, only when needed.
52
+
53
+ The default connection string is `ENV["DATABASE_URL"]`, so if you use that,
54
+ there is no need to configure anything.
55
+
56
+ Other configuration options, can be set via a block:
57
+
58
+ ``` ruby
59
+ namespace :db do
60
+ Communard::Rake.add_tasks do |config|
61
+
62
+ # Change where the application is located, defaults to Dir.pwd
63
+ config.root_path = Dir.pwd
64
+
65
+ # Automatically generate schema (default: false)
66
+ config.dump_after_migrating = false
67
+
68
+ # Dump types in native format (default) or Ruby (more portable)
69
+ config.same_db = true
70
+
71
+ # Add a logger
72
+ config.logger = Logger.new("log/migrations.log")
73
+
74
+ end
75
+ end
76
+ ```
77
+
78
+ Example with using `config/database.yml`:
79
+
80
+ ``` ruby
81
+ namespace :db do
82
+ environment = ENV["RAILS_ENV"] || "development"
83
+ all_config = YAML.load_file("config/database.yml")
84
+ Communard::Rake.add_tasks(config.fetch(environment))
85
+ end
86
+ ```
87
+
88
+ Note about test environment: Communard doesn't try to create a test database
89
+ like ActiveRecord does. The only rake task that attempts to do that is
90
+ `rake db:test:prepare`. It respawns rake with different environment variables
91
+ set. Your mileage may vary.
92
+
63
93
  ### Migrations
64
94
 
65
95
  To generate a migration:
66
96
 
67
97
  ```
68
- $ bundle exec communard --generate-migration create_posts
98
+ $ communard migration create_posts
69
99
  ```
70
100
 
71
101
  Communard doesn't support more arguments, like the Rails generator does. You'll
72
102
  have to edit the generated migration file yourself.
73
103
 
74
- ### Configuration
75
-
76
- There are a couple of configuration options available. They can be set by giving
77
- a block to `connect` or `add_tasks`. Under normal circumstances you don't need
78
- to set them.
79
-
80
- ``` ruby
81
- DB = Communard.connect { |config|
82
- config.root = Rails.root
83
- config.logger = Rails.logger
84
- config.environment = Rails.env.to_s
85
- }
86
- ```
104
+ Communard supports both timestamps and integer versions. It automatically
105
+ detects which type you have. If you have no migrations yet and want to use
106
+ timestamps, add `--timestamps`. Read more about how to choose in the
107
+ [Sequel docs][tm].
87
108
 
88
109
  ## Contributing
89
110
 
90
- 1. Fork it ( https://github.com/yourkarma/communard/fork )
111
+ 1. Fork it ( https://github.com/iain/communard/fork )
91
112
  2. Create your feature branch (`git checkout -b my-new-feature`)
92
113
  3. Commit your changes (`git commit -am 'Add some feature'`)
93
114
  4. Push to the branch (`git push origin my-new-feature`)
@@ -95,3 +116,4 @@ DB = Communard.connect { |config|
95
116
 
96
117
  [ar]: http://rubyonrails.org
97
118
  [sq]: http://sequel.jeremyevans.net
119
+ [tm]: http://sequel.jeremyevans.net/rdoc/files/doc/migration_rdoc.html#label-How+to+choose
data/bin/communard CHANGED
@@ -1,26 +1,54 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "communard"
4
- require "optparse"
3
+ command = ARGV.shift
5
4
 
6
- parser = OptionParser.new do |opts|
5
+ case command
7
6
 
8
- opts.on "-m", "--generate-migration NAME", "Generates a migration" do |name|
9
- Communard.context.generate_migration(name: name)
10
- exit
11
- end
7
+ when nil, "-h", "--help", "help"
8
+ puts "Usage: communard migration NAME"
9
+ exit
10
+
11
+ when "-v", "--version"
12
+ require "communard"
13
+ puts Communard::VERSION
14
+ exit
15
+
16
+ when "migration", "-m", "--generate-migration", "m"
17
+ migration_name = ARGV.shift
18
+
19
+ require "optparse"
20
+ require "pathname"
21
+ require "fileutils"
22
+
23
+ migrations_dir = Pathname(Dir.pwd).join("db/migrate")
24
+ FileUtils.mkdir_p(migrations_dir)
25
+
26
+ migration_files = Pathname.glob(migrations_dir.join("*.rb")).map { |f| f.basename.to_s }
12
27
 
13
- opts.on_tail "-v", "--version" do
14
- puts "Communard version #{Communard::VERSION}"
15
- exit
28
+ if (conflict = migration_files.find { |f| f.match?(/\A\d+_#{migration_name}.rb\z/) })
29
+ abort "Migration with same name already exists: #{conflict}"
16
30
  end
17
31
 
18
- opts.on_tail "-h", "--help" do
19
- puts parser
20
- exit
32
+ options = {}
33
+
34
+ OptionParser.new do |opts|
35
+ opts.on "--[no-]timestamps", "Use timestamps for versions" do |bool|
36
+ options[:use_timestamps] = bool
37
+ end
38
+ end.parse!
39
+
40
+ versions = migration_files.map { |file| file.to_s.split("_", 2).first.to_i }
41
+
42
+ if !options.has_key?(:use_timestamps)
43
+ options[:use_timestamps] = versions.any? { |v| v > 20000101 }
21
44
  end
22
45
 
23
- end
24
- parser.parse!
46
+ version = options[:use_timestamps] ? Time.now.strftime("%Y%m%d%H%M%S") : "%03d" % (versions.max.to_i + 1)
47
+
48
+ filename = migrations_dir.join("#{version}_#{migration_name}.rb")
25
49
 
26
- puts parser
50
+ File.open(filename, "w") { |f| f.puts "Sequel.migration do\n\n change do\n end\n\nend" }
51
+ puts "Migration generated: #{filename.relative_path_from(Pathname(Dir.pwd))}"
52
+ else
53
+ abort "Unknown command: #{command}"
54
+ end
data/communard.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["iain@iain.nl"]
11
11
  spec.summary = %q{Adds some conventions from ActiveRecord to Sequel.}
12
12
  spec.description = %q{Adds some conventions from ActiveRecord to Sequel.}
13
- spec.homepage = "https://github.com/yourkarma/communard"
13
+ spec.homepage = "https://github.com/iain/communard"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "sequel", "~> 4.13"
21
+ spec.add_dependency "sequel", "~> 5.2"
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.6"
24
24
  spec.add_development_dependency "rake"
@@ -0,0 +1,156 @@
1
+ require "forwardable"
2
+
3
+ module Communard
4
+ class Commands
5
+
6
+ extend Forwardable
7
+
8
+ attr_reader :configuration
9
+
10
+ def_delegators :configuration,
11
+ :connection,
12
+ :adapter,
13
+ :database_name,
14
+ :options,
15
+ :root_path
16
+
17
+ def initialize(configuration)
18
+ @configuration = configuration
19
+ Sequel.extension :migration, :core_extensions
20
+ end
21
+
22
+ def create_database
23
+ return if adapter == "sqlite"
24
+ run_without_database("CREATE DATABASE %{database_name}")
25
+ rescue Sequel::DatabaseError => error
26
+ if error.message.to_s =~ /database (.*) already exists/
27
+ configuration.default_logger.warn "Database #{$1} already exists."
28
+ else
29
+ raise
30
+ end
31
+ end
32
+
33
+ def drop_database
34
+ if adapter == "sqlite"
35
+ file = database_name
36
+ File.rm(file) if File.exist?(file)
37
+ else
38
+ run_without_database("DROP DATABASE IF EXISTS %{database_name}")
39
+ end
40
+ end
41
+
42
+ def migrate(target: nil)
43
+ target = Integer(target) if target
44
+ migrator(target: target, current: nil).run
45
+ dump_schema if target.nil? && configuration.dump_after_migrating
46
+ end
47
+
48
+ def seed
49
+ load seeds_file if seeds_file.exist?
50
+ end
51
+
52
+ def rollback(step: 1)
53
+ target = applied_migrations[-step - 1]
54
+ if target
55
+ migrate(target: target.split(/_/, 2).first)
56
+ else
57
+ fail ArgumentError, "Cannot roll back to #{step}"
58
+ end
59
+ end
60
+
61
+ def load_schema
62
+ migration = instance_eval(schema_file.read, schema_file.expand_path.to_s, 1)
63
+ conn = configuration.silent_connection
64
+ migration.apply(conn, :up)
65
+ end
66
+
67
+ def dump_schema
68
+ conn = configuration.silent_connection
69
+ conn.extension :schema_dumper
70
+ schema = conn.dump_schema_migration(same_db: configuration.same_db)
71
+ schema_file.open("w") { |f| f.puts schema.gsub(/^\s+$/m, "").gsub(/:(\w+)=>/, '\1: ') }
72
+ end
73
+
74
+ def status
75
+ results = Hash.new { |h, k| h[k] = Status.new(k, false, false) }
76
+ available = Pathname.glob(migrations_dir.join("*.rb")).map(&:basename).map(&:to_s)
77
+ available.each { |migration| results[migration].available = true }
78
+ applied_migrations(available).each { |migration| results[migration].applied = true }
79
+
80
+ $stdout.puts
81
+ $stdout.puts "database: #{connection.opts.fetch(:database)}"
82
+ $stdout.puts
83
+ $stdout.puts " Status Migration ID Migration Name"
84
+ $stdout.puts "--------------------------------------------------"
85
+ results.values.sort.each do |result|
86
+ $stdout.puts " %-7s %-15s %s" % [ result.status, result.id, result.name ]
87
+ end
88
+ $stdout.puts
89
+ end
90
+
91
+ def run_without_database(query)
92
+ opts = options.dup
93
+ database_name = opts.delete("database")
94
+ if adapter == "postgres"
95
+ opts["database"] = "postgres"
96
+ opts["schema_search_path"] = "public"
97
+ end
98
+ conn = Sequel.connect(opts)
99
+ conn.run(query % { database_name: database_name })
100
+ end
101
+
102
+ private
103
+
104
+ def applied_migrations(available)
105
+ m = migrator(allow_missing_migration_files: true)
106
+ if m.is_a?(Sequel::IntegerMigrator)
107
+ available.select { |f| f.split("_", 2).first.to_i <= m.current }
108
+ else
109
+ instance.applied_migrations
110
+ end
111
+ end
112
+
113
+ def migrator(opts = {})
114
+ migrator = Sequel::Migrator.migrator_class(migrations_dir)
115
+ migrator.new(connection, migrations_dir, opts)
116
+ end
117
+
118
+ def schema_file
119
+ root_path.join("db/schema.rb")
120
+ end
121
+
122
+ def seeds_file
123
+ root_path.join("db/seeds.rb")
124
+ end
125
+
126
+ def migrations_dir
127
+ root_path.join("db/migrate")
128
+ end
129
+
130
+ Status = Struct.new(:file, :applied, :available) do
131
+
132
+ def <=>(other)
133
+ id <=> other.id
134
+ end
135
+
136
+ def status
137
+ return "????" unless available
138
+ applied ? " up " : "down"
139
+ end
140
+
141
+ def id
142
+ splitted.first
143
+ end
144
+
145
+ def name
146
+ splitted.last.capitalize.tr("_", " ").sub(/\.rb$/, "")
147
+ end
148
+
149
+ def splitted
150
+ file.split(/_/, 2)
151
+ end
152
+
153
+ end
154
+
155
+ end
156
+ end
@@ -1,52 +1,97 @@
1
+ require "pathname"
2
+ require "logger"
3
+ require "uri"
4
+
1
5
  module Communard
2
6
  class Configuration
3
7
 
4
- attr_accessor :environment, :root, :dump_same_db, :loggers, :sql_log_level, :log_warn_duration
8
+ attr_reader :options
9
+
10
+ def initialize(conn_string = ENV["DATABASE_URL"], opts = Sequel::OPTS)
11
+ @conn_string = conn_string
12
+ @opts = opts
13
+
14
+ case conn_string
15
+ when String
16
+ uri = URI.parse(conn_string)
17
+ @options = {
18
+ "adapter" => uri.scheme,
19
+ "user" => uri.user,
20
+ "password" => uri.password,
21
+ "port" => uri.port,
22
+ "host" => uri.hostname,
23
+ "database" => (m = %r{/(.*)}.match(uri.path)) && (m[1]),
24
+ }
25
+ when Hash
26
+ @options = conn_string.map { |k, v| [ k.to_s, v ] }.to_h
27
+ else
28
+ raise ArgumentError, "Sequel::Database.connect takes either a Hash or a String, given: #{conn_string.inspect}"
29
+ end
30
+
31
+ self.root_path = Dir.pwd
32
+ self.logger = nil
33
+ self.dump_after_migrating = true
34
+ self.same_db = true
5
35
 
6
- def initialize
7
- self.environment = ENV["RACK_ENV"] || ENV["RUBY_ENV"] || ENV["RACK_ENV"] || "development"
8
- self.root = Pathname(Dir.pwd)
9
- self.logger = stdout_logger
10
- self.log_level = :info
11
- self.dump_same_db = false
12
- self.sql_log_level = :debug
13
- self.log_warn_duration = 0.5
14
36
  yield self if block_given?
15
37
  end
16
38
 
17
- def dump_same_db!
18
- self.dump_same_db = true
19
- end
39
+ attr_accessor :logger
40
+
41
+ attr_accessor :same_db
42
+
43
+ attr_accessor :dump_after_migrating
20
44
 
21
- def logger=(logger)
22
- self.loggers = [logger]
45
+ attr_reader :root_path
46
+
47
+ def root_path=(path)
48
+ @root_path = Pathname(path)
23
49
  end
24
50
 
25
- def loggers
26
- Array(@loggers).compact
51
+ def connection
52
+ Sequel.connect(@conn_string, @opts).tap { |c|
53
+ c.loggers = [logger, default_logger].compact
54
+ c.sql_log_level = :debug
55
+ }
27
56
  end
28
57
 
29
- def log_level=(level)
30
- real_level = ::Logger.const_get(level.to_s.upcase)
31
- loggers.each do |logger|
32
- logger.level = real_level
33
- end
58
+ def silent_connection
59
+ Sequel.connect(@conn_string, @opts).tap { |c|
60
+ c.loggers = [logger].compact
61
+ }
34
62
  end
35
63
 
36
- def stdout_logger(out = $stdout)
64
+ def default_logger(out = $stdout)
37
65
  ::Logger.new(out).tap { |l|
38
66
  alternate = 0
39
67
  l.formatter = Proc.new { |sev, _, _, msg|
40
68
  alternate = ((alternate + 1) % 2)
41
- color = case sev
42
- when "INFO" then 35 + alternate
43
- when "DEBUG" then 90
44
- else 31
69
+ msg = if sev == "DEBUG"
70
+ " #{msg}"
71
+ else
72
+ "[#{sev}] #{msg}"
73
+ end
74
+ if out.tty?
75
+ color = case sev
76
+ when "INFO" then 35 + alternate
77
+ when "DEBUG" then 30
78
+ else 31
79
+ end
80
+ "\e[#{color}m#{msg}\e[0m\n"
81
+ else
82
+ "#{msg}\n"
45
83
  end
46
- "\e[#{color}m[#{sev}]\e[0m #{msg}\n"
47
84
  }
48
85
  }
49
86
  end
50
87
 
88
+ def adapter
89
+ options.fetch("adapter")
90
+ end
91
+
92
+ def database_name
93
+ options.fetch("database")
94
+ end
95
+
51
96
  end
52
97
  end
@@ -5,83 +5,87 @@ module Communard
5
5
 
6
6
  extend ::Rake::DSL if defined?(::Rake::DSL)
7
7
 
8
- def self.add_tasks(ns = :db, &block)
9
-
10
- namespace ns do
11
- task :_load_communard do
12
- @_communard_context = Communard.context(&block)
13
- end
8
+ def self.add_tasks(*args, &block)
9
+ task :_load_communard do
10
+ @_communard_commands = Communard.commands(*args, &block)
11
+ end
14
12
 
15
- desc "Creates the database, migrate the schema, and loads seed data"
16
- task :setup => [:create, :migrate, :seed, "db:test:prepare"]
13
+ desc "Creates the database, migrate the schema, and loads seed data"
14
+ task setup: ["db:create", "db:migrate", "db:seed", "db:test:prepare"]
17
15
 
18
- desc "Creates the database"
19
- task :create => :_load_communard do
20
- @_communard_context.create_database
21
- end
16
+ desc "Creates the database"
17
+ task create: :_load_communard do
18
+ @_communard_commands.create_database
19
+ end
22
20
 
23
- desc "Drops the database"
24
- task :drop => :_load_communard do
25
- @_communard_context.drop_database
26
- end
21
+ desc "Drops the database"
22
+ task drop: :_load_communard do
23
+ @_communard_commands.drop_database
24
+ end
27
25
 
28
- desc "Drops and creates the database"
29
- task :reset => [:drop, :setup]
26
+ desc "Drops and creates the database"
27
+ task reset: ["db:drop", "db:setup"]
30
28
 
31
- desc "Migrate the database"
32
- task :migrate => :_load_communard do
33
- target = ENV["VERSION"] || ENV["TARGET"]
34
- @_communard_context.migrate(target: target)
35
- end
29
+ desc "Migrate the database"
30
+ task migrate: :_load_communard do
31
+ target = ENV["TARGET"]
32
+ @_communard_commands.migrate(target: target)
33
+ end
36
34
 
37
- desc "Load the seed data from db/seeds.rb"
38
- task :seed => :_load_communard do
39
- @_communard_context.seed
40
- end
35
+ desc "Load the seed data from db/seeds.rb"
36
+ task seed: :_load_communard do
37
+ @_communard_commands.seed
38
+ end
41
39
 
42
- desc "Rolls the schema back to the previous version"
43
- task :rollback => :_load_communard do
44
- step = Integer(ENV["STEP"] || 1)
45
- @_communard_context.rollback(step: step)
46
- end
40
+ desc "Rolls the schema back to the previous version"
41
+ task rollback: :_load_communard do
42
+ step = Integer(ENV["STEP"] || 1)
43
+ @_communard_commands.rollback(step: step)
44
+ end
47
45
 
48
- namespace :test do
49
- desc "Cleans the test database"
50
- task :prepare => :_load_communard do
51
- context = @_communard_context
52
- context.drop_database(env: "test")
53
- context.create_database(env: "test")
54
- context.migrate(env: "test")
55
- end
46
+ namespace :test do
47
+ desc "Cleans the test database"
48
+ task prepare: :_load_communard do
49
+ env = {
50
+ "RACK_ENV" => "test",
51
+ "RAILS_ENV" => "test",
52
+ "RUBY_ENV" => "test",
53
+ "DATABASE_URL" => nil,
54
+ }
55
+ Process.spawn(env, $PROGRAM_NAME, "db:drop", "db:create", "db:schema:load")
56
+ _pid, status = Process.wait2
57
+ fail "Failed to re-create test database" if status.exitstatus != 0
56
58
  end
59
+ end
57
60
 
58
- namespace :migrate do
61
+ namespace :migrate do
59
62
 
60
- desc "Redo the last migration"
61
- task :redo => :_load_communard do
62
- context = @_communard_context
63
- context.rollback
64
- context.migrate
65
- end
63
+ desc "Redo the last migration"
64
+ task redo: :_load_communard do
65
+ commands = @_communard_commands
66
+ commands.rollback
67
+ commands.migrate
68
+ end
66
69
 
67
- desc "Display status of migrations"
68
- task :status, :_load_communard do
69
- @_communard_context.status
70
- end
70
+ desc "Display status of migrations"
71
+ task status: :_load_communard do
72
+ @_communard_commands.status
71
73
  end
72
74
 
73
- namespace :schema do
75
+ desc "Drop and recreate database with migrations"
76
+ task reset: ["db:drop", "db:create", "db:migrate"]
77
+ end
74
78
 
75
- desc "Load the schema from db/schema.rb"
76
- task :load => :_load_communard do
77
- @_communard_context.load_schema
78
- end
79
+ namespace :schema do
79
80
 
80
- desc "Dumps the schema to db/schema.rb"
81
- task :dump => :_load_communard do
82
- @_communard_context.dump_schema
83
- end
81
+ desc "Load the schema from db/schema.rb"
82
+ task load: :_load_communard do
83
+ @_communard_commands.load_schema
84
+ end
84
85
 
86
+ desc "Dumps the schema to db/schema.rb"
87
+ task dump: :_load_communard do
88
+ @_communard_commands.dump_schema
85
89
  end
86
90
 
87
91
  end
@@ -1,3 +1,5 @@
1
1
  module Communard
2
- VERSION = "0.0.5"
2
+
3
+ VERSION = "0.1.0"
4
+
3
5
  end
data/lib/communard.rb CHANGED
@@ -1,24 +1,17 @@
1
- require "sequel"
2
- require "logger"
3
- require "pathname"
1
+ require "sequel/core"
4
2
 
5
3
  require "communard/version"
6
- require "communard/maintenance"
7
4
  require "communard/configuration"
8
- require "communard/context"
5
+ require "communard/commands"
9
6
 
10
7
  module Communard
11
8
 
12
- def self.connect(&block)
13
- context(&block).connect
9
+ def self.commands(*args, &block)
10
+ Commands.new(configuration(*args, &block))
14
11
  end
15
12
 
16
- def self.context(&block)
17
- Context.new(configuration(&block))
18
- end
19
-
20
- def self.configuration(&block)
21
- Configuration.new(&block)
13
+ def self.configuration(*args, &block)
14
+ Configuration.new(*args, &block)
22
15
  end
23
16
 
24
17
  end
@@ -3,57 +3,34 @@ require "yaml"
3
3
  RSpec.describe "Integration", type: :aruba do
4
4
 
5
5
  example "SQLite" do
6
- run_tests(
7
- "adapter" => "sqlite",
8
- "database" => "db/test.sqlite3",
9
- "pool" => 5,
10
- "timeout" => 5000,
11
- )
6
+ run_tests("sqlite://db/test.sqlite3")
12
7
  end
13
8
 
14
9
  example "PostgreSQL" do
15
- run_tests(
16
- "adapter" => "postgres",
17
- "database" => "communard_test",
18
- "pool" => 5,
19
- "timeout" => 5000,
20
- )
10
+ run_tests("postgresql://localhost:5432/communard_test")
21
11
  end
22
12
 
23
13
  example "MySQL" do
24
- run_tests(
25
- "adapter" => "mysql2",
26
- "database" => "communard_test",
27
- "username" => "root",
28
- "pool" => 5,
29
- "timeout" => 5000,
30
- )
14
+ run_tests("mysql2://root@localhost:3306/communard_test")
31
15
  end
32
16
 
33
-
34
17
  def run_tests(database_config)
35
-
36
- write_file "config/database.yml", { "development" => database_config }.to_yaml
37
-
38
18
  write_file "Rakefile", <<-FILE.gsub(/^\s{6}/, "")
39
19
  $LOAD_PATH.unshift(File.expand_path("../../../lib", __FILE__))
40
- require "yaml"
41
20
  require "communard/rake"
42
- Communard::Rake.add_tasks
21
+ namespace :db do
22
+ Communard::Rake.add_tasks("#{database_config}")
23
+ end
43
24
  FILE
44
25
 
45
- run_simple "bundle exec communard --generate-migration create_posts"
26
+ run_simple "bundle exec communard migration create_posts"
46
27
 
47
- file = Dir[absolute_path("db/migrate/*_create_posts.rb")].first
28
+ glob = Dir[expand_path("db/migrate/*_create_posts.rb")]
29
+ file = glob.first
48
30
 
49
- expect(File.read(file)).to eq <<-FILE.gsub(/^\s{6}/, "").chomp
50
- Sequel.migration do
51
- change do
52
- end
53
- end
54
- FILE
31
+ expect(File.read(file)).to eq "Sequel.migration do\n\n change do\n end\n\nend\n"
55
32
 
56
- write_file file, <<-FILE.gsub(/^\s{6}/, "")
33
+ write_file "db/migrate/#{File.basename(file)}", <<-FILE.gsub(/^\s{6}/, "")
57
34
  Sequel.migration do
58
35
  change do
59
36
  create_table :posts do
@@ -64,31 +41,11 @@ RSpec.describe "Integration", type: :aruba do
64
41
  end
65
42
  FILE
66
43
 
67
- run_simple "rake db:drop"
68
-
69
- run_simple "rake db:create"
44
+ run_simple "bundle exec rake db:drop"
70
45
 
71
- run_simple "rake db:migrate"
46
+ run_simple "bundle exec rake db:create"
72
47
 
73
- write_file "app.rb", <<-FILE.gsub(/^\s{6}/, "")
74
- $LOAD_PATH.unshift(File.expand_path("../../../lib", __FILE__))
75
- require "yaml"
76
- require "communard"
77
-
78
- db = Communard.connect
79
- posts = db[:posts]
80
-
81
- 4.times do
82
- posts.insert(name: "hello world")
83
- end
84
-
85
- puts "Post count: '\#{posts.count}'"
86
- FILE
87
-
88
- run_simple "ruby app.rb"
89
-
90
- assert_partial_output("Post count: '4'", all_stdout)
48
+ run_simple "bundle exec rake db:migrate"
91
49
  end
92
50
 
93
-
94
51
  end
data/spec/spec_helper.rb CHANGED
@@ -1,22 +1,12 @@
1
- require 'aruba/api'
2
- require 'aruba/reporting'
1
+ require "aruba"
3
2
 
4
3
  RSpec.configure do |config|
5
4
  config.disable_monkey_patching!
6
5
  config.include Aruba::Api, type: :aruba
7
6
 
8
- config.before :each do
9
- next unless self.class.include?(Aruba::Api)
7
+ config.before :each, type: :aruba do
10
8
  restore_env
11
- clean_current_dir
12
-
13
- if ENV["DEBUG"] == "true"
14
- @announce_stdout = true
15
- @announce_stderr = true
16
- @announce_cmd = true
17
- @announce_dir = true
18
- @announce_env = true
19
- end
9
+ setup_aruba
20
10
  end
21
11
 
22
12
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: communard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - iain
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-17 00:00:00.000000000 Z
11
+ date: 2017-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '4.13'
19
+ version: '5.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '4.13'
26
+ version: '5.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -139,14 +139,13 @@ files:
139
139
  - bin/communard
140
140
  - communard.gemspec
141
141
  - lib/communard.rb
142
+ - lib/communard/commands.rb
142
143
  - lib/communard/configuration.rb
143
- - lib/communard/context.rb
144
- - lib/communard/maintenance.rb
145
144
  - lib/communard/rake.rb
146
145
  - lib/communard/version.rb
147
146
  - spec/integration_spec.rb
148
147
  - spec/spec_helper.rb
149
- homepage: https://github.com/yourkarma/communard
148
+ homepage: https://github.com/iain/communard
150
149
  licenses:
151
150
  - MIT
152
151
  metadata: {}
@@ -166,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
165
  version: '0'
167
166
  requirements: []
168
167
  rubyforge_project:
169
- rubygems_version: 2.4.5
168
+ rubygems_version: 2.7.1
170
169
  signing_key:
171
170
  specification_version: 4
172
171
  summary: Adds some conventions from ActiveRecord to Sequel.
@@ -1,118 +0,0 @@
1
- module Communard
2
- class Context
3
-
4
- attr_reader :configuration
5
-
6
- def initialize(configuration)
7
- @configuration = configuration
8
- end
9
-
10
- def connect(opts = options)
11
- ::Sequel.connect(opts).tap do |connection|
12
- connection.loggers = loggers
13
- connection.sql_log_level = configuration.sql_log_level
14
- connection.log_warn_duration = configuration.log_warn_duration
15
- end
16
- end
17
-
18
- def generate_migration(name: nil)
19
- fail ArgumentError, "Name is required" if name.to_s == ""
20
- require "fileutils"
21
- underscore = name.
22
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
23
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
24
- tr("-", "_").
25
- downcase
26
- filename = root.join("db/migrate/#{Time.now.strftime("%Y%m%d%H%M%S")}_#{underscore}.rb")
27
- FileUtils.mkdir_p(File.dirname(filename))
28
- File.open(filename, "w") { |f| f << "Sequel.migration do\n change do\n end\nend" }
29
- puts "#{filename} created"
30
- end
31
-
32
- def create_database(env: environment)
33
- unless adapter(env: env) == "sqlite"
34
- run_without_database("CREATE DATABASE %{database_name}", env: env)
35
- end
36
- rescue Sequel::DatabaseError => error
37
- if /database (.*) already exists/ === error.message
38
- loggers.each { |logger| logger.info "Database #{$1} already exists, which is fine." }
39
- else
40
- raise
41
- end
42
- end
43
-
44
- def drop_database(env: environment)
45
- fail ArgumentError, "Don't drop the production database, you monkey!" if env.to_s == "production"
46
- if adapter(env: env) == "sqlite"
47
- file = options(env: env).fetch("database")
48
- if File.exist?(file)
49
- File.rm(file)
50
- end
51
- else
52
- run_without_database("DROP DATABASE IF EXISTS %{database_name}", env: env)
53
- end
54
- end
55
-
56
- def migrate(target: nil, env: environment)
57
- maintenance(env: env).migrate(target: target, dump_same_db: configuration.dump_same_db)
58
- end
59
-
60
- def seed(env: environment)
61
- maintenance(env: env).seed
62
- end
63
-
64
- def rollback(step: 1, env: environment)
65
- maintenance(env: env).rollback(step: step, dump_same_db: configuration.dump_same_db)
66
- end
67
-
68
- def load_schema(env: environment)
69
- maintenance(env: env).load_schema
70
- end
71
-
72
- def dump_schema(env: environment)
73
- maintenance(env: env).dump_schema(dump_same_db: configuration.dump_same_db)
74
- end
75
-
76
- def status(env: environment)
77
- maintenance(env: env).status
78
- end
79
-
80
- def run_without_database(cmd, env: environment)
81
- opts = options(env: env).dup
82
- database_name = opts.delete("database")
83
- if opts.fetch("adapter") == "postgres"
84
- opts["database"] = "postgres"
85
- opts["schema_search_path"] = "public"
86
- end
87
- connection = connect(opts)
88
- connection.run(cmd % { database_name: database_name })
89
- end
90
-
91
- def options(env: environment)
92
- YAML.load_file(root.join("config/database.yml")).fetch(env.to_s)
93
- end
94
-
95
- private
96
-
97
- def maintenance(env: environment)
98
- Maintenance.new(connection: connect(options(env: env)), root: root)
99
- end
100
-
101
- def environment
102
- configuration.environment
103
- end
104
-
105
- def root
106
- configuration.root
107
- end
108
-
109
- def loggers
110
- configuration.loggers
111
- end
112
-
113
- def adapter(env: environment)
114
- options(env: env).fetch("adapter").to_s
115
- end
116
-
117
- end
118
- end
@@ -1,102 +0,0 @@
1
- module Communard
2
- class Maintenance
3
-
4
- attr_reader :connection, :root
5
-
6
- def initialize(connection: nil, root: nil)
7
- ::Sequel.extension :migration, :core_extensions
8
- @connection = connection
9
- @root = root
10
- end
11
-
12
- def migrate(target: nil, dump_same_db: false)
13
- target = Integer(target) if target
14
- ::Sequel::Migrator.run(connection, migrations, target: target, allow_missing_migration_files: true)
15
- dump_schema(dump_same_db: dump_same_db)
16
- end
17
-
18
- def seed
19
- load seeds_file if seeds_file.exist?
20
- end
21
-
22
- def rollback(step: 1, dump_same_db: false)
23
- target = applied_migrations[-step - 1]
24
- if target
25
- migrate(target: target.split(/_/, 2).first, dump_same_db: dump_same_db)
26
- else
27
- fail ArgumentError, "Cannot roll back that far"
28
- end
29
- end
30
-
31
- def load_schema
32
- migration = instance_eval(schema_file.read, schema_file.expand_path.to_s, 1)
33
- migration.apply(connection, :up)
34
- end
35
-
36
- def dump_schema(dump_same_db: false)
37
- connection.extension :schema_dumper
38
- schema = connection.dump_schema_migration(same_db: dump_same_db)
39
- schema_file.open("w") { |f| f << schema.gsub(/\s+$/m, "") }
40
- end
41
-
42
- def status
43
- results = Hash.new { |h,k| h[k] = Status.new(k, false, false) }
44
- available = Pathname.glob(migrations.join("*.rb")).map(&:basename).map(&:to_s).reverse
45
- available.each { |migration| results[migration].available = true }
46
- applied_migrations.each { |migration| results[migration].applied = true }
47
-
48
- puts
49
- puts "database: #{connection.opts.fetch(:database)}"
50
- puts
51
- puts " Status Migration ID Migration Name"
52
- puts "--------------------------------------------------"
53
- results.values.sort.each do |result|
54
- puts " #{result.status} #{result.id} #{result.name}"
55
- end
56
- puts
57
- end
58
-
59
- private
60
-
61
- def applied_migrations
62
- ::Sequel::Migrator.migrator_class(migrations).new(connection, migrations, allow_missing_migration_files: true).applied_migrations
63
- end
64
-
65
- def schema_file
66
- root.join("db/schema.rb")
67
- end
68
-
69
- def seeds_file
70
- root.join("db/seeds.rb")
71
- end
72
-
73
- def migrations
74
- root.join("db/migrate")
75
- end
76
-
77
- Status = Struct.new(:file, :applied, :available) do
78
-
79
- def <=>(other)
80
- id <=> other.id
81
- end
82
-
83
- def status
84
- available ? applied ? " up " : "down" : "????"
85
- end
86
-
87
- def id
88
- splitted.first
89
- end
90
-
91
- def name
92
- splitted.last.capitalize.gsub("_", " ").sub(/\.rb$/, "")
93
- end
94
-
95
- def splitted
96
- file.split(/_/, 2)
97
- end
98
-
99
- end
100
-
101
- end
102
- end