active_record_mysql_repl 0.1.3 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +729 -13
- data/lib/active_record_mysql_repl/cli/erd.rb +1 -1
- data/lib/active_record_mysql_repl/cli/main.rb +19 -14
- data/lib/active_record_mysql_repl/cli/zsh_completion.rb +23 -23
- data/lib/active_record_mysql_repl/cli.rb +4 -4
- data/lib/active_record_mysql_repl/config.rb +7 -7
- data/lib/active_record_mysql_repl/database/association.rb +10 -10
- data/lib/active_record_mysql_repl/database/configs.rb +2 -2
- data/lib/active_record_mysql_repl/database/connection.rb +11 -13
- data/lib/active_record_mysql_repl/database/loader.rb +10 -5
- data/lib/active_record_mysql_repl/database.rb +4 -4
- data/lib/active_record_mysql_repl/extensions/active_record.rb +8 -8
- data/lib/active_record_mysql_repl/extensions/global.rb +0 -1
- data/lib/active_record_mysql_repl/extensions/hash.rb +8 -5
- data/lib/active_record_mysql_repl/extensions/object.rb +53 -54
- data/lib/active_record_mysql_repl/extensions/tabler.rb +2 -3
- data/lib/active_record_mysql_repl/extensions.rb +5 -6
- data/lib/active_record_mysql_repl/ssh_tunnel.rb +5 -3
- data/lib/active_record_mysql_repl/version.rb +1 -1
- data/lib/active_record_mysql_repl.rb +4 -5
- data/sample_config/{.pryrc.sample → .army.sample/.pryrc.sample} +2 -0
- data/sample_config/{associations.sample.yml → .army.sample/associations.sample.yml} +1 -1
- data/sample_config/{databases.sample.yml → .army.sample/databases.sample.yml} +2 -2
- data/sample_config/.army.sample/extensions/hello.rb +9 -0
- data/sample_config/.army.sample.yml +4 -4
- metadata +20 -5
@@ -1,43 +1,48 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
3
|
+
require "pry"
|
4
|
+
require "colorize"
|
5
|
+
require "active_support"
|
6
|
+
require "active_support/core_ext"
|
7
|
+
require "fileutils"
|
8
8
|
|
9
9
|
module ActiveRecordMysqlRepl
|
10
10
|
module CLI
|
11
11
|
module Main
|
12
12
|
def self.run(args)
|
13
|
-
if args
|
13
|
+
if args.empty?
|
14
|
+
puts "ActiveRecordMysqlRepl Version: #{VERSION}"
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
if args[0] == "--zsh-completion"
|
14
19
|
puts ZshCompletion.generate
|
15
20
|
return
|
16
21
|
end
|
17
22
|
|
18
23
|
opts = CLI::Options.parse(args)
|
19
|
-
army_config = Config.load(opts[:c] || File.join(Dir.home,
|
24
|
+
army_config = Config.load(opts[:c] || File.join(Dir.home, ".army.yml"))
|
20
25
|
|
21
26
|
db_configs = Database::Configs.load(army_config.database_config)
|
22
27
|
db_config_key = opts[:d]
|
23
28
|
db_config = db_configs[db_config_key]
|
24
29
|
return puts db_configs.keys unless db_config
|
25
30
|
|
26
|
-
generate_erf = opts[:e] ==
|
31
|
+
generate_erf = opts[:e] == "erd"
|
27
32
|
|
28
33
|
SSHTunnel.tunnel(db_config) do |port|
|
29
34
|
Database::Connection.connect(db_config, port) do
|
30
35
|
Database::Loader.load_tables(db_config_key, army_config, port)
|
31
36
|
|
32
37
|
if generate_erf
|
33
|
-
require
|
38
|
+
require "rails_erd/diagram/graphviz"
|
34
39
|
puts "Generating ERD for #{db_config_key}_erd.pdf".gray
|
35
40
|
RailsERD::Diagram::Graphviz.create
|
36
|
-
FileUtils.mv(
|
37
|
-
|
41
|
+
FileUtils.mv("erd.pdf", "#{db_config_key}_erd.pdf")
|
42
|
+
next
|
38
43
|
end
|
39
44
|
|
40
|
-
require
|
45
|
+
require "active_record_mysql_repl/extensions"
|
41
46
|
if army_config.extensions_dir.present?
|
42
47
|
puts "Loading custom extensions from #{army_config.extensions_dir}".gray
|
43
48
|
Extensions.load_external(army_config.extensions_dir)
|
@@ -52,8 +57,8 @@ module ActiveRecordMysqlRepl
|
|
52
57
|
end
|
53
58
|
|
54
59
|
def self.clear_screen
|
55
|
-
system(
|
56
|
-
system(
|
60
|
+
system("clear")
|
61
|
+
system("cls")
|
57
62
|
end
|
58
63
|
end
|
59
64
|
end
|
@@ -1,29 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
COMPLETION = <<~COMPLETION
|
4
|
-
#!/usr/bin/env bash
|
5
|
-
|
6
|
-
function _army() {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
}
|
21
|
-
|
22
|
-
function _database {
|
23
|
-
|
24
|
-
}
|
25
|
-
|
26
|
-
compdef _army army
|
4
|
+
#!/usr/bin/env bash
|
5
|
+
|
6
|
+
function _army() {
|
7
|
+
_arguments \
|
8
|
+
'-c[path to .armyrc file]:.armyrc:_files' \
|
9
|
+
'-d[Database name]:database:->database' \
|
10
|
+
'-e[output erd]:output erd:->erd'
|
11
|
+
|
12
|
+
case "$state" in
|
13
|
+
database)
|
14
|
+
slice=("${words[@]:1}")
|
15
|
+
_values 'Database name' $(_database ${slice})
|
16
|
+
;;
|
17
|
+
erd)
|
18
|
+
_values 'Generate ERD' erd ''
|
19
|
+
esac
|
20
|
+
}
|
21
|
+
|
22
|
+
function _database {
|
23
|
+
army ${@}
|
24
|
+
}
|
25
|
+
|
26
|
+
compdef _army army
|
27
27
|
COMPLETION
|
28
28
|
|
29
29
|
module ActiveRecordMysqlRepl
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
3
|
+
require_relative "cli/options"
|
4
|
+
require_relative "cli/main"
|
5
|
+
require_relative "cli/zsh_completion"
|
6
|
+
require_relative "cli/erd"
|
7
7
|
|
8
8
|
module ActiveRecordMysqlRepl
|
9
9
|
module CLI; end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "yaml"
|
4
4
|
|
5
5
|
module ActiveRecordMysqlRepl
|
6
6
|
class Config
|
@@ -9,12 +9,12 @@ module ActiveRecordMysqlRepl
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def database_config
|
12
|
-
raise
|
12
|
+
raise "database_config is not defined" unless @database_config
|
13
13
|
File.join(@army_config_dir, @database_config)
|
14
14
|
end
|
15
15
|
|
16
16
|
def associations
|
17
|
-
File.join(@army_config_dir, @associations)
|
17
|
+
File.join(@army_config_dir, @associations) if @associations.present?
|
18
18
|
end
|
19
19
|
|
20
20
|
def extensions_dir
|
@@ -29,10 +29,10 @@ module ActiveRecordMysqlRepl
|
|
29
29
|
|
30
30
|
def initialize(path, config)
|
31
31
|
@army_config_dir = File.dirname(File.absolute_path(path))
|
32
|
-
@database_config = config[
|
33
|
-
@associations = config[
|
34
|
-
@extensions_dir = config[
|
35
|
-
@pryrc = config[
|
32
|
+
@database_config = config["database_config"]
|
33
|
+
@associations = config["associations"]
|
34
|
+
@extensions_dir = config["extensions_dir"]
|
35
|
+
@pryrc = config["pryrc"]
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -27,7 +27,7 @@ module ActiveRecordMysqlRepl
|
|
27
27
|
|
28
28
|
# Analyze the relationship between tables based on the information of *_id columns
|
29
29
|
# For example, if users.company_id exists, users belongs_to companies and companies has_many users
|
30
|
-
def self.analyze(tables, association_settings)
|
30
|
+
def self.analyze(tables, association_settings = {})
|
31
31
|
analyzed_tables = tables.map { |table| [table, AnalyzedTable.new(table)] }.to_h
|
32
32
|
|
33
33
|
analyzed_tables.each do |table_name, table|
|
@@ -36,18 +36,18 @@ module ActiveRecordMysqlRepl
|
|
36
36
|
columns.each do |column|
|
37
37
|
next if association_setting.present? && association_settings.ignore_columns(table_name).include?(column.name)
|
38
38
|
|
39
|
-
associatable = column.name.gsub(/_id$/,
|
40
|
-
next if associatable.blank? || associatable ==
|
39
|
+
associatable = column.name.gsub(/_id$/, "") if column.name.end_with?("_id")
|
40
|
+
next if associatable.blank? || associatable == "class" # reserved word
|
41
41
|
|
42
|
-
if analyzed_tables.
|
42
|
+
if analyzed_tables.key?(associatable.pluralize)
|
43
43
|
table.belongs_to << associatable.singularize if associatable
|
44
44
|
analyzed_tables[associatable.pluralize].has_many << table_name.pluralize
|
45
45
|
else
|
46
|
-
associatable_table_name = associatable.split(
|
47
|
-
if analyzed_tables.
|
48
|
-
|
46
|
+
associatable_table_name = associatable.split("_").last
|
47
|
+
table.belongs_to << if analyzed_tables.key?(associatable_table_name.pluralize)
|
48
|
+
{name: associatable, class_name: associatable_table_name.classify, foreign_key: :id}
|
49
49
|
else
|
50
|
-
|
50
|
+
{name: associatable, class_name: table_name.singularize.classify, foreign_key: :id}
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -71,12 +71,12 @@ module ActiveRecordMysqlRepl
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def [](table)
|
74
|
-
table = (@association.keys - [
|
74
|
+
table = (@association.keys - ["ignore_columns"]) & [table]
|
75
75
|
@association[table.first] if table.present?
|
76
76
|
end
|
77
77
|
|
78
78
|
def ignore_columns(table)
|
79
|
-
@association.fetch(
|
79
|
+
@association.fetch("ignore_columns", {}).fetch(table, [])
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
@@ -27,7 +27,7 @@ module ActiveRecordMysqlRepl
|
|
27
27
|
private
|
28
28
|
|
29
29
|
class Config
|
30
|
-
attr_reader
|
30
|
+
attr_reader(*%i[
|
31
31
|
bastion
|
32
32
|
ssh_user
|
33
33
|
remote_host
|
@@ -36,7 +36,7 @@ module ActiveRecordMysqlRepl
|
|
36
36
|
user
|
37
37
|
password
|
38
38
|
prompt_color
|
39
|
-
]
|
39
|
+
])
|
40
40
|
|
41
41
|
def initialize(config)
|
42
42
|
@bastion = config["bastion"]
|
@@ -7,28 +7,26 @@ module ActiveRecordMysqlRepl
|
|
7
7
|
|
8
8
|
def self.connect(db_config, port)
|
9
9
|
conn = {
|
10
|
-
adapter:
|
11
|
-
host:
|
10
|
+
adapter: "mysql2",
|
11
|
+
host: "127.0.0.1",
|
12
12
|
port: port,
|
13
13
|
username: db_config.user,
|
14
14
|
password: db_config.password,
|
15
|
-
database: db_config.database
|
15
|
+
database: db_config.database
|
16
16
|
}
|
17
17
|
|
18
|
-
ActiveRecord::Base.logger = Logger.new(
|
19
|
-
|
18
|
+
ActiveRecord::Base.logger = Logger.new($stdout)
|
19
|
+
ActiveRecord::Base.establish_connection(conn)
|
20
20
|
|
21
21
|
puts "Ensureing connection to #{db_config.database} on port 127.0.0.1:#{port}".gray
|
22
22
|
|
23
23
|
tables = nil
|
24
|
-
(1..MAX_RETRY-1).to_a.each do |time|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
next
|
31
|
-
end
|
24
|
+
(1..MAX_RETRY - 1).to_a.each do |time|
|
25
|
+
tables = ActiveRecord::Base.connection.tables
|
26
|
+
rescue => e
|
27
|
+
puts "#{e}, Retry #{time}/#{MAX_RETRY}".red
|
28
|
+
sleep time * time
|
29
|
+
next
|
32
30
|
end
|
33
31
|
|
34
32
|
if tables.blank?
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "json"
|
4
|
+
require "active_record"
|
5
|
+
require "active_support/all"
|
6
6
|
|
7
7
|
module ActiveRecordMysqlRepl
|
8
8
|
module Database
|
@@ -11,9 +11,14 @@ module ActiveRecordMysqlRepl
|
|
11
11
|
puts "Loading tables".gray
|
12
12
|
|
13
13
|
tables = ActiveRecord::Base.connection.tables
|
14
|
-
association_settings = Associations.load(army_config.associations)
|
14
|
+
association_settings = army_config.associations.present? ? Associations.load(army_config.associations) : {}
|
15
|
+
association_setting = association_settings[db_config_key]
|
16
|
+
analyzed_tables = if association_setting.present?
|
17
|
+
Associations.analyze(tables, association_setting)
|
18
|
+
else
|
19
|
+
Associations.analyze(tables)
|
20
|
+
end
|
15
21
|
|
16
|
-
analyzed_tables = Associations.analyze(tables, association_settings[db_config_key])
|
17
22
|
skipped = []
|
18
23
|
analyzed_tables.each do |analyzed_table|
|
19
24
|
# defer model definition for tables with `has_many: :xxx, through: xxx` associations
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
3
|
+
require_relative "database/configs"
|
4
|
+
require_relative "database/association"
|
5
|
+
require_relative "database/connection"
|
6
|
+
require_relative "database/loader"
|
7
7
|
|
8
8
|
module ActiveRecordMysqlRepl
|
9
9
|
module Database; end
|
@@ -5,28 +5,28 @@ module ActiverecordMysqlRepl
|
|
5
5
|
module ActiveRecord
|
6
6
|
module Base
|
7
7
|
def as(name = nil)
|
8
|
-
|
8
|
+
reflect_on_all_associations(name).map(&:name)
|
9
9
|
end
|
10
10
|
|
11
11
|
def describe
|
12
12
|
[
|
13
|
-
|
14
|
-
exec_sql("
|
13
|
+
"# #{table_name}",
|
14
|
+
exec_sql("DESCRIBE #{table_name}").tab(:h),
|
15
|
+
exec_sql("SHOW INDEX FROM #{table_name}").tab(:h)
|
15
16
|
].join("\n")
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
alias_method :desc, :describe
|
20
|
+
alias_method :d, :describe
|
20
21
|
|
21
22
|
def show_ddl
|
22
|
-
exec_sql("SHOW CREATE TABLE #{
|
23
|
+
exec_sql("SHOW CREATE TABLE #{table_name}")[0]["Create Table"]
|
23
24
|
end
|
24
25
|
|
25
|
-
|
26
|
+
alias_method :ddl, :show_ddl
|
26
27
|
end
|
27
28
|
|
28
29
|
::ActiveRecord::Base.extend(Base)
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
32
|
-
|
@@ -4,17 +4,20 @@ module ActiverecordMysqlRepl
|
|
4
4
|
module Extensions
|
5
5
|
module Hash
|
6
6
|
def method_missing(name, *args)
|
7
|
-
if (
|
7
|
+
if (keys & [name, name.to_s]).present?
|
8
8
|
self[name] || self[name.to_s]
|
9
|
-
elsif name.to_s.end_with?(
|
9
|
+
elsif name.to_s.end_with?("=") && keys.include?(name.to_s[0..-2])
|
10
10
|
name = name[0..-2]
|
11
|
-
self[name] = args.first if
|
12
|
-
self[name.to_sym] = args.first if
|
11
|
+
self[name] = args.first if key?(name)
|
12
|
+
self[name.to_sym] = args.first if key?(name.to_sym)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
def respond_to_missing?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
16
20
|
::Hash.include(Hash)
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
20
|
-
|
@@ -1,28 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require "terminal-table"
|
4
|
+
require "csv"
|
5
|
+
require "clipboard"
|
6
|
+
require "json"
|
7
7
|
|
8
8
|
module ActiverecordMysqlRepl
|
9
9
|
module Extensions
|
10
10
|
module Object
|
11
11
|
def tabulate(orientation = nil)
|
12
|
-
arr = if
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
arr = if is_a?(Array)
|
13
|
+
self
|
14
|
+
elsif is_a?(::ActiveRecord::Relation)
|
15
|
+
to_a
|
16
|
+
else
|
17
|
+
[self]
|
18
|
+
end
|
19
19
|
|
20
20
|
arr = arr.map do |e|
|
21
21
|
if e.is_a?(::ActiveRecord::Base)
|
22
|
-
values =
|
22
|
+
values = e.attributes.transform_values do |v|
|
23
23
|
next JSON.pretty_generate(v) if v.is_a?(Enumerable) && v.size > 0
|
24
|
-
next
|
25
|
-
next '""' if v ==
|
24
|
+
next "NULL" if v.nil?
|
25
|
+
next '""' if v == ""
|
26
26
|
v.to_s
|
27
27
|
end
|
28
28
|
next values
|
@@ -34,17 +34,17 @@ module ActiverecordMysqlRepl
|
|
34
34
|
raise "#{arr} contains Hashes with different keys".red unless arr.map(&:keys).uniq.size == 1
|
35
35
|
|
36
36
|
orientation = case orientation
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
37
|
+
when :vertical, :v
|
38
|
+
:vertical
|
39
|
+
when :horizontal, :h
|
40
|
+
:horizontal
|
41
|
+
else
|
42
|
+
if arr.first.keys.size > 5
|
43
|
+
:vertical
|
44
|
+
else
|
45
|
+
:horizontal
|
46
|
+
end
|
47
|
+
end
|
48
48
|
|
49
49
|
t = Terminal::Table.new
|
50
50
|
|
@@ -54,7 +54,7 @@ module ActiverecordMysqlRepl
|
|
54
54
|
t.rows = arr.map(&:values)
|
55
55
|
|
56
56
|
when :vertical
|
57
|
-
t.headings = [
|
57
|
+
t.headings = ["Name", "Value"]
|
58
58
|
arr.each.with_index do |row, i|
|
59
59
|
row.each { |col, val| t.add_row [col, val] }
|
60
60
|
t.add_separator if i < arr.size - 1
|
@@ -64,25 +64,25 @@ module ActiverecordMysqlRepl
|
|
64
64
|
t.to_s
|
65
65
|
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
alias_method :tab, :tabulate
|
68
|
+
alias_method :table, :tabulate
|
69
|
+
alias_method :to_table, :tabulate
|
70
70
|
|
71
71
|
def csv(orientation = nil)
|
72
|
-
arr = if
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
72
|
+
arr = if is_a?(Array)
|
73
|
+
self
|
74
|
+
elsif is_a?(::ActiveRecord::Relation)
|
75
|
+
to_a
|
76
|
+
else
|
77
|
+
[self]
|
78
|
+
end
|
79
79
|
|
80
80
|
arr = arr.map do |e|
|
81
81
|
if e.is_a?(::ActiveRecord::Base)
|
82
|
-
values =
|
82
|
+
values = e.attributes.transform_values do |v|
|
83
83
|
next JSON.pretty_generate(v) if v.is_a?(Enumerable) && v.size > 0
|
84
|
-
next
|
85
|
-
next '""' if v ==
|
84
|
+
next "NULL" if v.nil?
|
85
|
+
next '""' if v == ""
|
86
86
|
v.to_s
|
87
87
|
end
|
88
88
|
next values
|
@@ -94,17 +94,17 @@ module ActiverecordMysqlRepl
|
|
94
94
|
raise "#{arr} contains Hashes with different keys".red unless arr.map(&:keys).uniq.size == 1
|
95
95
|
|
96
96
|
orientation = case orientation
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
97
|
+
when :vertical, :v
|
98
|
+
:vertical
|
99
|
+
when :horizontal, :h
|
100
|
+
:horizontal
|
101
|
+
else
|
102
|
+
if arr.first.keys.size > 5
|
103
|
+
:vertical
|
104
|
+
else
|
105
|
+
:horizontal
|
106
|
+
end
|
107
|
+
end
|
108
108
|
|
109
109
|
CSV.generate do |csv|
|
110
110
|
case orientation
|
@@ -121,11 +121,11 @@ module ActiverecordMysqlRepl
|
|
121
121
|
end
|
122
122
|
|
123
123
|
def copy
|
124
|
-
Clipboard.copy(
|
124
|
+
Clipboard.copy(to_s)
|
125
125
|
end
|
126
|
-
|
126
|
+
alias_method :cp, :copy
|
127
127
|
|
128
|
-
|
128
|
+
alias_method :j, :to_json
|
129
129
|
|
130
130
|
def jp
|
131
131
|
JSON.pretty_generate(JSON.parse(to_json))
|
@@ -135,4 +135,3 @@ module ActiverecordMysqlRepl
|
|
135
135
|
|
136
136
|
::Object.include(Extensions::Object)
|
137
137
|
end
|
138
|
-
|
@@ -13,11 +13,11 @@ module ActiverecordMysqlRepl
|
|
13
13
|
end
|
14
14
|
|
15
15
|
model.column_names.each do |column|
|
16
|
-
define_method("#{model.table_name.singularize}_by_#{column}") do
|
16
|
+
define_method(:"#{model.table_name.singularize}_by_#{column}") do
|
17
17
|
model.where(column => self)
|
18
18
|
end
|
19
19
|
|
20
|
-
define_method("#{model.table_name.singularize}_#{column}_like") do
|
20
|
+
define_method(:"#{model.table_name.singularize}_#{column}_like") do
|
21
21
|
model.where("#{column} like ?", "%#{self}%")
|
22
22
|
end
|
23
23
|
end
|
@@ -29,4 +29,3 @@ module ActiverecordMysqlRepl
|
|
29
29
|
Enumerable.include Tabler
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
3
|
+
require_relative "extensions/object"
|
4
|
+
require_relative "extensions/global"
|
5
|
+
require_relative "extensions/active_record"
|
6
|
+
require_relative "extensions/hash"
|
7
|
+
require_relative "extensions/tabler"
|
8
8
|
|
9
9
|
module ActiveRecordMysqlRepl
|
10
10
|
module Extensions
|
@@ -15,4 +15,3 @@ module ActiveRecordMysqlRepl
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
@@ -1,14 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "net/ssh"
|
4
|
+
require "net/ssh/gateway"
|
5
5
|
|
6
6
|
module ActiveRecordMysqlRepl
|
7
7
|
module SSHTunnel
|
8
8
|
EPHEMERAL_PORT = 0
|
9
9
|
|
10
10
|
def self.tunnel(db_config)
|
11
|
-
|
11
|
+
unless db_config.bastion
|
12
|
+
return yield(db_config.port) if block_given?
|
13
|
+
end
|
12
14
|
|
13
15
|
puts "Establishing ssh tunnel to #{db_config.remote_host}:#{db_config.port} via #{db_config.ssh_user}#{db_config.bastion}".gray
|
14
16
|
|