ardb 0.26.0 → 0.27.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ardb.gemspec +1 -0
- data/bin/ardb +1 -1
- data/lib/ardb.rb +1 -1
- data/lib/ardb/adapter/base.rb +73 -66
- data/lib/ardb/adapter/sqlite.rb +1 -1
- data/lib/ardb/adapter_spy.rb +18 -5
- data/lib/ardb/cli.rb +239 -76
- data/lib/ardb/clirb.rb +58 -0
- data/lib/ardb/default_order_by.rb +59 -0
- data/lib/ardb/has_slug.rb +7 -6
- data/lib/ardb/migration.rb +42 -0
- data/lib/ardb/migration_helpers.rb +56 -53
- data/lib/ardb/record_spy.rb +5 -5
- data/lib/ardb/relation_spy.rb +13 -2
- data/lib/ardb/root_path.rb +7 -4
- data/lib/ardb/test_helpers.rb +56 -42
- data/lib/ardb/use_db_default.rb +8 -7
- data/lib/ardb/version.rb +1 -1
- data/test/support/factory.rb +5 -0
- data/test/unit/adapter/base_tests.rb +22 -5
- data/test/unit/adapter/mysql_tests.rb +1 -1
- data/test/unit/adapter/sqlite_tests.rb +2 -2
- data/test/unit/adapter_spy_tests.rb +19 -6
- data/test/unit/cli_tests.rb +610 -0
- data/test/unit/default_order_by_tests.rb +122 -0
- data/test/unit/has_slug_tests.rb +5 -0
- data/test/unit/migration_tests.rb +88 -0
- data/test/unit/record_spy_tests.rb +6 -0
- data/test/unit/test_helpers_tests.rb +26 -3
- data/test/unit/use_db_default_tests.rb +5 -0
- metadata +31 -25
- data/lib/ardb/runner.rb +0 -50
- data/lib/ardb/runner/connect_command.rb +0 -20
- data/lib/ardb/runner/create_command.rb +0 -25
- data/lib/ardb/runner/drop_command.rb +0 -25
- data/lib/ardb/runner/generate_command.rb +0 -64
- data/lib/ardb/runner/migrate_command.rb +0 -28
- data/test/unit/runner/connect_command_tests.rb +0 -17
- data/test/unit/runner/create_command_tests.rb +0 -67
- data/test/unit/runner/drop_command_tests.rb +0 -68
- data/test/unit/runner/generate_command_tests.rb +0 -46
- data/test/unit/runner/migrate_command_tests.rb +0 -96
- data/test/unit/runner_tests.rb +0 -69
data/lib/ardb/clirb.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
module Ardb
|
2
|
+
|
3
|
+
class CLIRB # Version 1.0.0, https://github.com/redding/cli.rb
|
4
|
+
Error = Class.new(RuntimeError);
|
5
|
+
HelpExit = Class.new(RuntimeError); VersionExit = Class.new(RuntimeError)
|
6
|
+
attr_reader :argv, :args, :opts, :data
|
7
|
+
|
8
|
+
def initialize(&block)
|
9
|
+
@options = []; instance_eval(&block) if block
|
10
|
+
require 'optparse'
|
11
|
+
@data, @args, @opts = [], [], {}; @parser = OptionParser.new do |p|
|
12
|
+
p.banner = ''; @options.each do |o|
|
13
|
+
@opts[o.name] = o.value; p.on(*o.parser_args){ |v| @opts[o.name] = v }
|
14
|
+
end
|
15
|
+
p.on_tail('--version', ''){ |v| raise VersionExit, v.to_s }
|
16
|
+
p.on_tail('--help', ''){ |v| raise HelpExit, v.to_s }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def option(*args); @options << Option.new(*args); end
|
21
|
+
def parse!(argv)
|
22
|
+
@args = (argv || []).dup.tap do |args_list|
|
23
|
+
begin; @parser.parse!(args_list)
|
24
|
+
rescue OptionParser::ParseError => err; raise Error, err.message; end
|
25
|
+
end; @data = @args + [@opts]
|
26
|
+
end
|
27
|
+
def to_s; @parser.to_s; end
|
28
|
+
def inspect
|
29
|
+
"#<#{self.class}:#{'0x0%x' % (object_id << 1)} @data=#{@data.inspect}>"
|
30
|
+
end
|
31
|
+
|
32
|
+
class Option
|
33
|
+
attr_reader :name, :opt_name, :desc, :abbrev, :value, :klass, :parser_args
|
34
|
+
|
35
|
+
def initialize(name, *args)
|
36
|
+
settings, @desc = args.last.kind_of?(::Hash) ? args.pop : {}, args.pop || ''
|
37
|
+
@name, @opt_name, @abbrev = parse_name_values(name, settings[:abbrev])
|
38
|
+
@value, @klass = gvalinfo(settings[:value])
|
39
|
+
@parser_args = if [TrueClass, FalseClass, NilClass].include?(@klass)
|
40
|
+
["-#{@abbrev}", "--[no-]#{@opt_name}", @desc]
|
41
|
+
else
|
42
|
+
["-#{@abbrev}", "--#{@opt_name} #{@opt_name.upcase}", @klass, @desc]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def parse_name_values(name, custom_abbrev)
|
49
|
+
[ (processed_name = name.to_s.strip.downcase), processed_name.gsub('_', '-'),
|
50
|
+
custom_abbrev || processed_name.gsub(/[^a-z]/, '').chars.first || 'a'
|
51
|
+
]
|
52
|
+
end
|
53
|
+
def gvalinfo(v); v.kind_of?(Class) ? [nil,gklass(v)] : [v,gklass(v.class)]; end
|
54
|
+
def gklass(k); k == Fixnum ? Integer : k; end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'much-plugin'
|
2
|
+
|
3
|
+
module Ardb
|
4
|
+
|
5
|
+
module DefaultOrderBy
|
6
|
+
include MuchPlugin
|
7
|
+
|
8
|
+
DEFAULT_ATTRIBUTE = :order_by
|
9
|
+
DEFAULT_SCOPE_PROC = proc{ self.class.scoped }
|
10
|
+
|
11
|
+
plugin_included do
|
12
|
+
extend ClassMethods
|
13
|
+
include InstanceMethods
|
14
|
+
|
15
|
+
@ardb_default_order_by_config = {}
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
|
21
|
+
def default_order_by(options = nil)
|
22
|
+
options ||= {}
|
23
|
+
|
24
|
+
@ardb_default_order_by_config.merge!({
|
25
|
+
:attribute => options[:attribute] || DEFAULT_ATTRIBUTE,
|
26
|
+
:scope_proc => options[:scope] || DEFAULT_SCOPE_PROC
|
27
|
+
})
|
28
|
+
|
29
|
+
before_validation :ardb_default_order_by, :on => :create
|
30
|
+
end
|
31
|
+
|
32
|
+
def ardb_default_order_by_config
|
33
|
+
@ardb_default_order_by_config
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
module InstanceMethods
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def reset_order_by
|
43
|
+
attr_name = self.class.ardb_default_order_by_config[:attribute]
|
44
|
+
scope_proc = self.class.ardb_default_order_by_config[:scope_proc]
|
45
|
+
|
46
|
+
current_max = self.instance_eval(&scope_proc).maximum(attr_name) || 0
|
47
|
+
self.send("#{attr_name}=", current_max + 1)
|
48
|
+
end
|
49
|
+
|
50
|
+
def ardb_default_order_by
|
51
|
+
attr_name = self.class.ardb_default_order_by_config[:attribute]
|
52
|
+
reset_order_by if self.send(attr_name).to_s.empty?
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
data/lib/ardb/has_slug.rb
CHANGED
@@ -1,19 +1,20 @@
|
|
1
|
+
require 'much-plugin'
|
2
|
+
|
1
3
|
module Ardb
|
2
4
|
|
3
5
|
module HasSlug
|
6
|
+
include MuchPlugin
|
4
7
|
|
5
8
|
DEFAULT_ATTRIBUTE = :slug
|
6
9
|
DEFAULT_PREPROCESSOR = :downcase
|
7
10
|
DEFAULT_SEPARATOR = '-'.freeze
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
include InstanceMethods
|
12
|
+
plugin_included do
|
13
|
+
extend ClassMethods
|
14
|
+
include InstanceMethods
|
13
15
|
|
14
|
-
|
16
|
+
@ardb_has_slug_config = {}
|
15
17
|
|
16
|
-
end
|
17
18
|
end
|
18
19
|
|
19
20
|
module ClassMethods
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Ardb
|
4
|
+
|
5
|
+
class Migration
|
6
|
+
|
7
|
+
attr_reader :identifier, :class_name, :file_name, :file_path
|
8
|
+
attr_reader :source
|
9
|
+
|
10
|
+
def initialize(identifier)
|
11
|
+
raise NoIdentifierError if identifier.to_s.empty?
|
12
|
+
|
13
|
+
@identifier = identifier
|
14
|
+
@class_name = @identifier.classify.pluralize
|
15
|
+
@file_name = get_file_name(@identifier)
|
16
|
+
@file_path = File.join(Ardb.config.migrations_path, "#{@file_name}.rb")
|
17
|
+
|
18
|
+
@source = "require 'ardb/migration_helpers'\n\n" \
|
19
|
+
"class #{@class_name} < ActiveRecord::Migration\n" \
|
20
|
+
" include Ardb::MigrationHelpers\n\n" \
|
21
|
+
" def change\n" \
|
22
|
+
" end\n\n" \
|
23
|
+
"end\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
def save!
|
27
|
+
FileUtils.mkdir_p Ardb.config.migrations_path
|
28
|
+
File.open(self.file_path, 'w'){ |f| f.write(self.source) }
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def get_file_name(identifier)
|
35
|
+
"#{Time.now.strftime("%Y%m%d%H%M%S")}_#{identifier.underscore}"
|
36
|
+
end
|
37
|
+
|
38
|
+
NoIdentifierError = Class.new(ArgumentError)
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -1,72 +1,75 @@
|
|
1
1
|
require 'ardb'
|
2
2
|
|
3
|
-
module Ardb
|
4
|
-
module Ardb::MigrationHelpers
|
5
|
-
module_function
|
3
|
+
module Ardb
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
execute(fk.add_sql)
|
10
|
-
end
|
11
|
-
|
12
|
-
def drop_foreign_key(*args)
|
13
|
-
from_table, from_column = args[0..1]
|
14
|
-
options = args.last.kind_of?(Hash) ? args.last : {}
|
15
|
-
fk = ForeignKey.new(from_table, from_column, nil, options)
|
16
|
-
execute(fk.drop_sql)
|
17
|
-
end
|
18
|
-
|
19
|
-
def remove_column_with_fk(table, column)
|
20
|
-
drop_foreign_key(table, column)
|
21
|
-
remove_column(table, column)
|
22
|
-
end
|
5
|
+
module MigrationHelpers
|
6
|
+
module_function
|
23
7
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def initialize(from_table, from_column, to_table, options=nil)
|
28
|
-
options ||= {}
|
29
|
-
@from_table = from_table.to_s
|
30
|
-
@from_column = from_column.to_s
|
31
|
-
@to_table = to_table.to_s
|
32
|
-
@to_column = (options[:to_column] || 'id').to_s
|
33
|
-
@name = (options[:name] || "fk_#{@from_table}_#{@from_column}").to_s
|
34
|
-
@adapter = Ardb::Adapter.send(Ardb.config.db.adapter)
|
8
|
+
def foreign_key(from_table, from_column, to_table, options={})
|
9
|
+
fk = ForeignKey.new(from_table, from_column, to_table, options)
|
10
|
+
execute(fk.add_sql)
|
35
11
|
end
|
36
12
|
|
37
|
-
def
|
38
|
-
|
13
|
+
def drop_foreign_key(*args)
|
14
|
+
from_table, from_column = args[0..1]
|
15
|
+
options = args.last.kind_of?(Hash) ? args.last : {}
|
16
|
+
fk = ForeignKey.new(from_table, from_column, nil, options)
|
17
|
+
execute(fk.drop_sql)
|
39
18
|
end
|
40
19
|
|
41
|
-
def
|
42
|
-
|
20
|
+
def remove_column_with_fk(table, column)
|
21
|
+
drop_foreign_key(table, column)
|
22
|
+
remove_column(table, column)
|
43
23
|
end
|
44
24
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
25
|
+
class ForeignKey
|
26
|
+
attr_reader :from_table, :from_column, :to_table, :to_column, :name, :adapter
|
27
|
+
|
28
|
+
def initialize(from_table, from_column, to_table, options=nil)
|
29
|
+
options ||= {}
|
30
|
+
@from_table = from_table.to_s
|
31
|
+
@from_column = from_column.to_s
|
32
|
+
@to_table = to_table.to_s
|
33
|
+
@to_column = (options[:to_column] || 'id').to_s
|
34
|
+
@name = (options[:name] || "fk_#{@from_table}_#{@from_column}").to_s
|
35
|
+
@adapter = Ardb::Adapter.send(Ardb.config.db.adapter)
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_sql
|
39
|
+
apply_data(@adapter.foreign_key_add_sql)
|
40
|
+
end
|
41
|
+
|
42
|
+
def drop_sql
|
43
|
+
apply_data(@adapter.foreign_key_drop_sql)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def apply_data(template_sql)
|
49
|
+
template_sql.
|
50
|
+
gsub(':from_table', @from_table).
|
51
|
+
gsub(':from_column', @from_column).
|
52
|
+
gsub(':to_table', @to_table).
|
53
|
+
gsub(':to_column', @to_column).
|
54
|
+
gsub(':name', @name)
|
55
|
+
end
|
54
56
|
end
|
55
|
-
end
|
56
57
|
|
57
|
-
|
58
|
-
|
58
|
+
# This file will setup the AR migration command recorder for being able to
|
59
|
+
# change our stuff, require it in an initializer
|
59
60
|
|
60
|
-
|
61
|
+
module RecorderMixin
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
63
|
+
def foreign_key(*args)
|
64
|
+
record(:foreign_key, args)
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
65
68
|
|
66
|
-
|
69
|
+
def invert_foreign_key(args)
|
70
|
+
[ :drop_foreign_key, args ]
|
71
|
+
end
|
67
72
|
|
68
|
-
def invert_foreign_key(args)
|
69
|
-
[ :drop_foreign_key, args ]
|
70
73
|
end
|
71
74
|
|
72
75
|
end
|
data/lib/ardb/record_spy.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'arel'
|
2
|
+
require 'much-plugin'
|
2
3
|
require 'ardb/relation_spy'
|
3
4
|
|
4
5
|
module Ardb
|
5
6
|
|
6
7
|
module RecordSpy
|
8
|
+
include MuchPlugin
|
7
9
|
|
8
10
|
def self.new(&block)
|
9
11
|
block ||= proc{ }
|
@@ -12,11 +14,9 @@ module Ardb
|
|
12
14
|
record_spy
|
13
15
|
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
include InstanceMethods
|
19
|
-
end
|
17
|
+
plugin_included do
|
18
|
+
extend ClassMethods
|
19
|
+
include InstanceMethods
|
20
20
|
end
|
21
21
|
|
22
22
|
module ClassMethods
|
data/lib/ardb/relation_spy.rb
CHANGED
@@ -4,13 +4,16 @@ module Ardb
|
|
4
4
|
|
5
5
|
attr_reader :applied
|
6
6
|
attr_accessor :limit_value, :offset_value
|
7
|
-
attr_accessor :pluck_values
|
7
|
+
attr_accessor :pluck_values, :maximum_values, :minimum_values
|
8
8
|
attr_accessor :results
|
9
9
|
|
10
10
|
def initialize
|
11
11
|
@applied, @results = [], []
|
12
12
|
@offset_value, @limit_value = nil, nil
|
13
|
-
|
13
|
+
|
14
|
+
@pluck_values = {}
|
15
|
+
@maximum_values = {}
|
16
|
+
@minimum_values = {}
|
14
17
|
end
|
15
18
|
|
16
19
|
def initialize_copy(copied_from)
|
@@ -134,6 +137,14 @@ module Ardb
|
|
134
137
|
[@pluck_values[column_name]] * @results.size
|
135
138
|
end
|
136
139
|
|
140
|
+
def maximum(column_name)
|
141
|
+
@maximum_values[column_name]
|
142
|
+
end
|
143
|
+
|
144
|
+
def minimum(column_name)
|
145
|
+
@minimum_values[column_name]
|
146
|
+
end
|
147
|
+
|
137
148
|
class AppliedExpression < Struct.new(:type, :args)
|
138
149
|
def to_sql
|
139
150
|
"#{self.type}: #{self.args.inspect}"
|
data/lib/ardb/root_path.rb
CHANGED
@@ -2,11 +2,14 @@
|
|
2
2
|
# to the full qualifed root path. The goal here is to specify path options
|
3
3
|
# with root-relative path strings.
|
4
4
|
|
5
|
-
module Ardb
|
6
|
-
|
5
|
+
module Ardb
|
6
|
+
|
7
|
+
class RootPath < String
|
8
|
+
|
9
|
+
def initialize(path_string)
|
10
|
+
super(Ardb.config.root_path.join(path_string).to_s)
|
11
|
+
end
|
7
12
|
|
8
|
-
def initialize(path_string)
|
9
|
-
super(Ardb.config.root_path.join(path_string).to_s)
|
10
13
|
end
|
11
14
|
|
12
15
|
end
|
data/lib/ardb/test_helpers.rb
CHANGED
@@ -4,62 +4,76 @@ require 'ardb'
|
|
4
4
|
# Use theses helpers in your test suite. They all generally assume Ardb has
|
5
5
|
# already been initialized by calling `Ardb.init`.
|
6
6
|
|
7
|
-
module Ardb
|
8
|
-
module Ardb::TestHelpers
|
9
|
-
module_function
|
7
|
+
module Ardb
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
end
|
9
|
+
module TestHelpers
|
10
|
+
module_function
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
def drop_tables
|
13
|
+
Ardb.adapter.drop_tables
|
14
|
+
end
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
def load_schema
|
17
|
+
Ardb.adapter.load_schema
|
18
|
+
end
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
self.create_db!
|
26
|
-
true
|
20
|
+
def create_db!
|
21
|
+
Ardb.adapter.create_db
|
27
22
|
end
|
28
|
-
end
|
29
23
|
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
def create_db
|
25
|
+
@create_db ||= begin
|
26
|
+
self.create_db!
|
27
|
+
true
|
28
|
+
end
|
29
|
+
end
|
33
30
|
|
34
|
-
|
35
|
-
|
36
|
-
self.drop_db!
|
37
|
-
true
|
31
|
+
def drop_db!
|
32
|
+
Ardb.adapter.drop_db
|
38
33
|
end
|
39
|
-
end
|
40
34
|
|
41
|
-
|
42
|
-
|
43
|
-
|
35
|
+
def drop_db
|
36
|
+
@drop_db ||= begin
|
37
|
+
self.drop_db!
|
38
|
+
true
|
39
|
+
end
|
40
|
+
end
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
self.migrate_db!
|
48
|
-
true
|
42
|
+
def connect_db!
|
43
|
+
Ardb.adapter.connect_db
|
49
44
|
end
|
50
|
-
end
|
51
45
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
46
|
+
def connect_db
|
47
|
+
@connect_db ||= begin
|
48
|
+
self.connect_db!
|
49
|
+
true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def migrate_db!
|
54
|
+
Ardb.adapter.migrate_db
|
55
|
+
end
|
56
|
+
|
57
|
+
def migrate_db
|
58
|
+
@migrate_db ||= begin
|
59
|
+
self.migrate_db!
|
60
|
+
true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def reset_db!
|
65
|
+
self.drop_db!
|
66
|
+
self.create_db!
|
67
|
+
self.load_schema
|
68
|
+
end
|
57
69
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
70
|
+
def reset_db
|
71
|
+
@reset_db ||= begin
|
72
|
+
self.reset_db!
|
73
|
+
true
|
74
|
+
end
|
62
75
|
end
|
76
|
+
|
63
77
|
end
|
64
78
|
|
65
79
|
end
|