arql 0.3.31 → 0.4.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 +4 -4
 - data/.vscode/launch.json +1 -1
 - data/Gemfile.lock +1 -1
 - data/README-zh_CN.org +706 -429
 - data/auto-set-id-before-save-zh_CN.org +1 -1
 - data/custom-configurations-zh_CN.org +40 -3
 - data/define-associations-zh_CN.org +31 -17
 - data/initializer-structure-zh_CN.org +22 -4
 - data/lib/arql/app.rb +98 -71
 - data/lib/arql/cli.rb +31 -15
 - data/lib/arql/commands/info.rb +41 -28
 - data/lib/arql/commands/models.rb +106 -61
 - data/lib/arql/commands/reconnect.rb +8 -4
 - data/lib/arql/commands/redefine.rb +3 -1
 - data/lib/arql/commands/sandbox.rb +6 -4
 - data/lib/arql/commands.rb +0 -2
 - data/lib/arql/concerns/global_data_definition.rb +40 -6
 - data/lib/arql/concerns/model_extension.rb +168 -0
 - data/lib/arql/concerns/table_data_definition.rb +20 -20
 - data/lib/arql/concerns.rb +1 -0
 - data/lib/arql/definition.rb +169 -317
 - data/lib/arql/ext/active_record/relation.rb +29 -0
 - data/lib/arql/ext/active_record/result.rb +29 -0
 - data/lib/arql/ext/array.rb +40 -1
 - data/lib/arql/ext/kernel.rb +70 -61
 - data/lib/arql/ext/object.rb +14 -0
 - data/lib/arql/ext/ransack/search.rb +29 -0
 - data/lib/arql/mysqldump.rb +0 -1
 - data/lib/arql/ssh_proxy.rb +25 -22
 - data/lib/arql/version.rb +1 -1
 - data/lib/arql.rb +11 -7
 - data/sql-log-zh_CN.org +8 -3
 - metadata +6 -5
 - data/lib/arql/commands/table.rb +0 -55
 - data/lib/arql/commands/vd.rb +0 -46
 - data/lib/arql/connection.rb +0 -16
 
    
        data/lib/arql/commands/models.rb
    CHANGED
    
    | 
         @@ -3,84 +3,129 @@ require 'terminal-table' 
     | 
|
| 
       3 
3 
     | 
    
         
             
            module Arql::Commands
         
     | 
| 
       4 
4 
     | 
    
         
             
              module Models
         
     | 
| 
       5 
5 
     | 
    
         
             
                class << self
         
     | 
| 
       6 
     | 
    
         
            -
                  def  
     | 
| 
       7 
     | 
    
         
            -
                     
     | 
| 
       8 
     | 
    
         
            -
                     
     | 
| 
       9 
     | 
    
         
            -
                     
     | 
| 
       10 
     | 
    
         
            -
                     
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
                    if column_regexp.nil?
         
     | 
| 
       18 
     | 
    
         
            -
                      Terminal::Table.new do |t|
         
     | 
| 
       19 
     | 
    
         
            -
                        models.each_with_index { |row, idx| t << (row || :separator) if row.nil? ||
         
     | 
| 
       20 
     | 
    
         
            -
                          table_regexp.nil? ||
         
     | 
| 
       21 
     | 
    
         
            -
                          idx.zero? ||
         
     | 
| 
       22 
     | 
    
         
            -
                          row.any? { |e| e =~ table_regexp }
         
     | 
| 
       23 
     | 
    
         
            -
                        }
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def filter_tables(env_name, definition, format, table_regexp=nil)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    result = ''
         
     | 
| 
      
 8 
     | 
    
         
            +
                    result << '-- ' if format == 'sql'
         
     | 
| 
      
 9 
     | 
    
         
            +
                    result << "Environment: #{env_name}\n"
         
     | 
| 
      
 10 
     | 
    
         
            +
                    result << "------------------------------\n\n"
         
     | 
| 
      
 11 
     | 
    
         
            +
                    if format == 'sql'
         
     | 
| 
      
 12 
     | 
    
         
            +
                      definition.models.each do |model|
         
     | 
| 
      
 13 
     | 
    
         
            +
                        if table_regexp? || ( model[:table] =~ table_regexp || model[:comment] =~ table_regexp )
         
     | 
| 
      
 14 
     | 
    
         
            +
                          result << "-- Table: #{table_name}\n\n"
         
     | 
| 
      
 15 
     | 
    
         
            +
                          result << definition.connection.exec_query("show create table `#{table_name}`").rows.last.last + ';'
         
     | 
| 
      
 16 
     | 
    
         
            +
                        end
         
     | 
| 
       24 
17 
     | 
    
         
             
                      end
         
     | 
| 
       25 
18 
     | 
    
         
             
                    else
         
     | 
| 
       26 
     | 
    
         
            -
                       
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                        t << [' 
     | 
| 
      
 19 
     | 
    
         
            +
                      Terminal::Table.new do |t|
         
     | 
| 
      
 20 
     | 
    
         
            +
                        t.style = table_style_for_format(format)
         
     | 
| 
      
 21 
     | 
    
         
            +
                        t << ['Table Name', 'Model Class', 'Abbr', 'Comment']
         
     | 
| 
       29 
22 
     | 
    
         
             
                        t << :separator
         
     | 
| 
       30 
     | 
    
         
            -
                         
     | 
| 
       31 
     | 
    
         
            -
                           
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                          next if matched_columns.empty?
         
     | 
| 
       34 
     | 
    
         
            -
                          matched_columns.each do |column|
         
     | 
| 
       35 
     | 
    
         
            -
                            pk = if [connection.primary_key(definition[:table])].flatten.include?(column.name)
         
     | 
| 
       36 
     | 
    
         
            -
                                   'Y'
         
     | 
| 
       37 
     | 
    
         
            -
                                 else
         
     | 
| 
       38 
     | 
    
         
            -
                                   ''
         
     | 
| 
       39 
     | 
    
         
            -
                                 end
         
     | 
| 
       40 
     | 
    
         
            -
                            t << [pk, definition[:table], model_class.name, column.name, column.sql_type,
         
     | 
| 
       41 
     | 
    
         
            -
                                  column.sql_type_metadata.type, column.sql_type_metadata.limit || '',
         
     | 
| 
       42 
     | 
    
         
            -
                                  column.sql_type_metadata.precision || '', column.sql_type_metadata.scale || '', column.default || '',
         
     | 
| 
       43 
     | 
    
         
            -
                                  column.null, "#{definition[:comment]} - #{column.comment}"]
         
     | 
| 
      
 23 
     | 
    
         
            +
                        definition.models.each do |model|
         
     | 
| 
      
 24 
     | 
    
         
            +
                          if table_regexp.nil? || ( model[:table] =~ table_regexp || model[:comment] =~ table_regexp )
         
     | 
| 
      
 25 
     | 
    
         
            +
                            t << [model[:table], model[:model].name, model[:abbr] || '', model[:comment] || '']
         
     | 
| 
       44 
26 
     | 
    
         
             
                          end
         
     | 
| 
       45 
27 
     | 
    
         
             
                        end
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end.try { |e|
         
     | 
| 
      
 29 
     | 
    
         
            +
                        case format
         
     | 
| 
      
 30 
     | 
    
         
            +
                        when 'md'
         
     | 
| 
      
 31 
     | 
    
         
            +
                          result << e.to_s.lines.map { |l| '  ' + l }.join
         
     | 
| 
      
 32 
     | 
    
         
            +
                        when 'org'
         
     | 
| 
      
 33 
     | 
    
         
            +
                          result << e.to_s.lines.map { |l| '  ' + l.gsub(/^\+|\+$/, '|') }.join
         
     | 
| 
      
 34 
     | 
    
         
            +
                        else
         
     | 
| 
      
 35 
     | 
    
         
            +
                          result << e.to_s
         
     | 
| 
      
 36 
     | 
    
         
            +
                        end
         
     | 
| 
      
 37 
     | 
    
         
            +
                      }
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                    result
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  def filter_columns(env_name, definition, format, column_regexp=nil)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    result = ''
         
     | 
| 
      
 44 
     | 
    
         
            +
                    result << '-- ' if format == 'sql'
         
     | 
| 
      
 45 
     | 
    
         
            +
                    result << "Environment: #{env_name}\n"
         
     | 
| 
      
 46 
     | 
    
         
            +
                    result << "------------------------------\n\n"
         
     | 
| 
      
 47 
     | 
    
         
            +
                    Terminal::Table.new do |t|
         
     | 
| 
      
 48 
     | 
    
         
            +
                      t.style = table_style_for_format(format)
         
     | 
| 
      
 49 
     | 
    
         
            +
                      t << ['Table', 'Model', 'Name', 'SQL Type', 'Ruby Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
         
     | 
| 
      
 50 
     | 
    
         
            +
                      t << :separator
         
     | 
| 
      
 51 
     | 
    
         
            +
                      definition.models.each do |model_def|
         
     | 
| 
      
 52 
     | 
    
         
            +
                        model_class = model_def[:model]
         
     | 
| 
      
 53 
     | 
    
         
            +
                        matched_columns = model_class.columns.select { |column| column.name =~ column_regexp || column.comment =~ column_regexp }
         
     | 
| 
      
 54 
     | 
    
         
            +
                        next if matched_columns.empty?
         
     | 
| 
      
 55 
     | 
    
         
            +
                        matched_columns.each do |column|
         
     | 
| 
      
 56 
     | 
    
         
            +
                          t << [model_def[:table], model_class.name, column.name, column.sql_type,
         
     | 
| 
      
 57 
     | 
    
         
            +
                                column.sql_type_metadata.type, column.sql_type_metadata.limit || '',
         
     | 
| 
      
 58 
     | 
    
         
            +
                                column.sql_type_metadata.precision || '', column.sql_type_metadata.scale || '', column.default || '',
         
     | 
| 
      
 59 
     | 
    
         
            +
                                column.null, "#{model_def[:comment]} - #{column.comment}"]
         
     | 
| 
      
 60 
     | 
    
         
            +
                        end
         
     | 
| 
      
 61 
     | 
    
         
            +
                      end
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end.try { |e|
         
     | 
| 
      
 63 
     | 
    
         
            +
                      case format
         
     | 
| 
      
 64 
     | 
    
         
            +
                      when 'md'
         
     | 
| 
      
 65 
     | 
    
         
            +
                        result << e.to_s.lines.map { |l| '  ' + l }.join
         
     | 
| 
      
 66 
     | 
    
         
            +
                      when 'org'
         
     | 
| 
      
 67 
     | 
    
         
            +
                        result << e.to_s.lines.map { |l| '  ' + l.gsub(/^\+|\+$/, '|') }.join
         
     | 
| 
      
 68 
     | 
    
         
            +
                      else
         
     | 
| 
      
 69 
     | 
    
         
            +
                        result << e.to_s
         
     | 
| 
       46 
70 
     | 
    
         
             
                      end
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
      
 71 
     | 
    
         
            +
                    }
         
     | 
| 
      
 72 
     | 
    
         
            +
                    result
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  def table_style_for_format(format)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    case format
         
     | 
| 
      
 77 
     | 
    
         
            +
                    when 'md'
         
     | 
| 
      
 78 
     | 
    
         
            +
                      {
         
     | 
| 
      
 79 
     | 
    
         
            +
                        border_top: false,
         
     | 
| 
      
 80 
     | 
    
         
            +
                        border_bottom: false,
         
     | 
| 
      
 81 
     | 
    
         
            +
                        border_i: '|'
         
     | 
| 
      
 82 
     | 
    
         
            +
                      }
         
     | 
| 
      
 83 
     | 
    
         
            +
                    when 'org'
         
     | 
| 
      
 84 
     | 
    
         
            +
                      {
         
     | 
| 
      
 85 
     | 
    
         
            +
                        border_top: false,
         
     | 
| 
      
 86 
     | 
    
         
            +
                        border_bottom: false,
         
     | 
| 
      
 87 
     | 
    
         
            +
                      }
         
     | 
| 
      
 88 
     | 
    
         
            +
                    else
         
     | 
| 
      
 89 
     | 
    
         
            +
                      {}
         
     | 
| 
       48 
90 
     | 
    
         
             
                    end
         
     | 
| 
       49 
91 
     | 
    
         
             
                  end
         
     | 
| 
       50 
92 
     | 
    
         
             
                end
         
     | 
| 
       51 
93 
     | 
    
         
             
              end
         
     | 
| 
       52 
94 
     | 
    
         | 
| 
       53 
     | 
    
         
            -
              Pry.commands. 
     | 
| 
       54 
     | 
    
         
            -
                 
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                   
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                   
     | 
| 
      
 95 
     | 
    
         
            +
              Pry.commands.create_command 'm' do
         
     | 
| 
      
 96 
     | 
    
         
            +
                description 'List models or columns (specified by `-c`): m [-e env_name_regexp] -c [column_regexp] [table_regexp]'
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                def options(opt)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  opt.on '-e', '--env', 'Environment name regexp', argument: true, as: String, required: false, default: nil
         
     | 
| 
      
 100 
     | 
    
         
            +
                  opt.on '-f', '--format', 'Table format, available: terminal(default), md, org, sql', argument: true, as: String, required: false, default: 'terminal'
         
     | 
| 
      
 101 
     | 
    
         
            +
                  opt.on '-c', '--column', 'Column name regexp', argument: true, as: String, required: false, default: nil
         
     | 
| 
       60 
102 
     | 
    
         
             
                end
         
     | 
| 
       61 
     | 
    
         
            -
              end
         
     | 
| 
       62 
103 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
            end
         
     | 
| 
      
 104 
     | 
    
         
            +
                def process
         
     | 
| 
       65 
105 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
      
 106 
     | 
    
         
            +
                  if opts[:format] == 'sql' && opts[:column]
         
     | 
| 
      
 107 
     | 
    
         
            +
                    output.puts 'SQL format is not supported for column listing'
         
     | 
| 
      
 108 
     | 
    
         
            +
                    return
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
       70 
110 
     | 
    
         | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
              end
         
     | 
| 
      
 111 
     | 
    
         
            +
                  env_names = opts[:env].try {|e| [e]}.presence || Arql::App.environments
         
     | 
| 
      
 112 
     | 
    
         
            +
                  env_names = env_names.map { |e| e.start_with?('/') ? eval(e) : Regexp.new(e) }
         
     | 
| 
       74 
113 
     | 
    
         | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
              end
         
     | 
| 
      
 114 
     | 
    
         
            +
                  Arql::App.instance.definitions.each do |env_name, definition|
         
     | 
| 
      
 115 
     | 
    
         
            +
                    next unless env_names.any? { |e| env_name =~ e }
         
     | 
| 
       78 
116 
     | 
    
         | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
      
 117 
     | 
    
         
            +
                    output.puts
         
     | 
| 
      
 118 
     | 
    
         
            +
                    if opts[:column]
         
     | 
| 
      
 119 
     | 
    
         
            +
                      column_regexp = opts[:column]
         
     | 
| 
      
 120 
     | 
    
         
            +
                      output.puts Models::filter_columns(env_name, definition, opts[:format], column_regexp.try { |e| e.start_with?('/') ? eval(e) : Regexp.new(e) })
         
     | 
| 
      
 121 
     | 
    
         
            +
                    else
         
     | 
| 
      
 122 
     | 
    
         
            +
                      table_regexp = args&.first
         
     | 
| 
      
 123 
     | 
    
         
            +
                      output.puts Models::filter_tables(env_name, definition, opts[:format], table_regexp.try { |e| e.start_with?('/') ? eval(e) : Regexp.new(e) })
         
     | 
| 
      
 124 
     | 
    
         
            +
                    end
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
                end
         
     | 
| 
       82 
127 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
              def model_names
         
     | 
| 
       84 
     | 
    
         
            -
                models[2..-1].map(&:second)
         
     | 
| 
       85 
128 
     | 
    
         
             
              end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
              Pry.commands.alias_command 'l', 'm'
         
     | 
| 
       86 
131 
     | 
    
         
             
            end
         
     | 
| 
         @@ -2,13 +2,17 @@ module Arql::Commands 
     | 
|
| 
       2 
2 
     | 
    
         
             
              module Reconnect
         
     | 
| 
       3 
3 
     | 
    
         
             
                class << self
         
     | 
| 
       4 
4 
     | 
    
         
             
                  def reconnect
         
     | 
| 
       5 
     | 
    
         
            -
                    Arql:: 
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
      
 5 
     | 
    
         
            +
                    Arql::App.instance.definitions.each do |_, definition|
         
     | 
| 
      
 6 
     | 
    
         
            +
                      definition.ssh_proxy.reconnect if definition.options[:ssh].present?
         
     | 
| 
      
 7 
     | 
    
         
            +
                      definition.connection.reconnect! unless definition.connection.active?
         
     | 
| 
      
 8 
     | 
    
         
            +
                    end
         
     | 
| 
       7 
9 
     | 
    
         
             
                  end
         
     | 
| 
       8 
10 
     | 
    
         | 
| 
       9 
11 
     | 
    
         
             
                  def reconnect!
         
     | 
| 
       10 
     | 
    
         
            -
                    Arql:: 
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 12 
     | 
    
         
            +
                    Arql::App.instance.definitions.each do |_, definition|
         
     | 
| 
      
 13 
     | 
    
         
            +
                      definition.ssh_proxy.reconnect if definition.options[:ssh].present?
         
     | 
| 
      
 14 
     | 
    
         
            +
                      definition.connection.reconnect!
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
       12 
16 
     | 
    
         
             
                  end
         
     | 
| 
       13 
17 
     | 
    
         
             
                end
         
     | 
| 
       14 
18 
     | 
    
         | 
| 
         @@ -9,16 +9,18 @@ module Arql::Commands 
     | 
|
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
                  def enter
         
     | 
| 
       11 
11 
     | 
    
         
             
                    ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback(:checkout, :after, &@sandbox_callback)
         
     | 
| 
       12 
     | 
    
         
            -
                     
     | 
| 
      
 12 
     | 
    
         
            +
                    Arql::App.instance.definitions.each do |_, definition|
         
     | 
| 
      
 13 
     | 
    
         
            +
                      definition.connection.begin_transaction(joinable: false)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    end
         
     | 
| 
       13 
15 
     | 
    
         
             
                    @enabled = true
         
     | 
| 
       14 
16 
     | 
    
         
             
                  end
         
     | 
| 
       15 
17 
     | 
    
         | 
| 
       16 
18 
     | 
    
         
             
                  def quit
         
     | 
| 
       17 
19 
     | 
    
         
             
                    ActiveRecord::ConnectionAdapters::AbstractAdapter.skip_callback(:checkout, :after, &@sandbox_callback)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    Arql::App.instance.definitions.each do |_, definition|
         
     | 
| 
      
 21 
     | 
    
         
            +
                      definition.connection.rollback_transaction
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
       18 
23 
     | 
    
         
             
                    @enabled = false
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                    puts "begin_transaction callbacks removed."
         
     | 
| 
       21 
     | 
    
         
            -
                    puts "You still have open %d transactions open, don't forget commit or rollback them." % ActiveRecord::Base.connection.open_transactions if ActiveRecord::Base.connection.open_transactions > 0
         
     | 
| 
       22 
24 
     | 
    
         
             
                  end
         
     | 
| 
       23 
25 
     | 
    
         
             
                end
         
     | 
| 
       24 
26 
     | 
    
         | 
    
        data/lib/arql/commands.rb
    CHANGED
    
    | 
         @@ -1,11 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'arql/commands/info'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'arql/commands/models'
         
     | 
| 
       3 
     | 
    
         
            -
            require 'arql/commands/table'
         
     | 
| 
       4 
3 
     | 
    
         
             
            require 'arql/commands/reconnect'
         
     | 
| 
       5 
4 
     | 
    
         
             
            require 'arql/commands/redefine'
         
     | 
| 
       6 
5 
     | 
    
         
             
            require 'arql/commands/show_sql'
         
     | 
| 
       7 
6 
     | 
    
         
             
            require 'arql/commands/sandbox'
         
     | 
| 
       8 
     | 
    
         
            -
            require 'arql/commands/vd'
         
     | 
| 
       9 
7 
     | 
    
         | 
| 
       10 
8 
     | 
    
         
             
            module Arql::Commands
         
     | 
| 
       11 
9 
     | 
    
         
             
            end
         
     | 
| 
         @@ -159,7 +159,14 @@ module Arql 
     | 
|
| 
       159 
159 
     | 
    
         
             
                    #
         
     | 
| 
       160 
160 
     | 
    
         
             
                    # See also TableDefinition#column for details on how to create columns.
         
     | 
| 
       161 
161 
     | 
    
         
             
                    def create_table(table_name, **options, &blk)
         
     | 
| 
       162 
     | 
    
         
            -
                       
     | 
| 
      
 162 
     | 
    
         
            +
                      env_name = options[:env]
         
     | 
| 
      
 163 
     | 
    
         
            +
                      unless env_name
         
     | 
| 
      
 164 
     | 
    
         
            +
                        raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                        env_name = Arql::App.instance.environments.first
         
     | 
| 
      
 167 
     | 
    
         
            +
                      end
         
     | 
| 
      
 168 
     | 
    
         
            +
                      options = options.except(:env)
         
     | 
| 
      
 169 
     | 
    
         
            +
                      Arql::App.instance.definitions[env_name].connection.create_table(table_name, **options, &blk)
         
     | 
| 
       163 
170 
     | 
    
         
             
                    end
         
     | 
| 
       164 
171 
     | 
    
         | 
| 
       165 
172 
     | 
    
         
             
                    # Creates a new join table with the name created using the lexical order of the first two
         
     | 
| 
         @@ -201,7 +208,14 @@ module Arql 
     | 
|
| 
       201 
208 
     | 
    
         
             
                    #   ) ENGINE=InnoDB DEFAULT CHARSET=utf8
         
     | 
| 
       202 
209 
     | 
    
         
             
                    #
         
     | 
| 
       203 
210 
     | 
    
         
             
                    def create_join_table(table_1, table_2, column_options: {}, **options)
         
     | 
| 
       204 
     | 
    
         
            -
                       
     | 
| 
      
 211 
     | 
    
         
            +
                      env_name = options[:env]
         
     | 
| 
      
 212 
     | 
    
         
            +
                      unless env_name
         
     | 
| 
      
 213 
     | 
    
         
            +
                        raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                        env_name = Arql::App.instance.environments.first
         
     | 
| 
      
 216 
     | 
    
         
            +
                      end
         
     | 
| 
      
 217 
     | 
    
         
            +
                      options = options.except(:env)
         
     | 
| 
      
 218 
     | 
    
         
            +
                      Arql::App.instance.definitions[env_name].connection.create_join_table(table_1, table_2, column_options, **options)
         
     | 
| 
       205 
219 
     | 
    
         
             
                    end
         
     | 
| 
       206 
220 
     | 
    
         | 
| 
       207 
221 
     | 
    
         
             
                    # Drops a table from the database.
         
     | 
| 
         @@ -217,7 +231,14 @@ module Arql 
     | 
|
| 
       217 
231 
     | 
    
         
             
                    # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
         
     | 
| 
       218 
232 
     | 
    
         
             
                    # In that case, +options+ and the block will be used by #create_table.
         
     | 
| 
       219 
233 
     | 
    
         
             
                    def drop_table(table_name, **options)
         
     | 
| 
       220 
     | 
    
         
            -
                       
     | 
| 
      
 234 
     | 
    
         
            +
                      env_name = options[:env]
         
     | 
| 
      
 235 
     | 
    
         
            +
                      unless env_name
         
     | 
| 
      
 236 
     | 
    
         
            +
                        raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                        env_name = Arql::App.instance.environments.first
         
     | 
| 
      
 239 
     | 
    
         
            +
                      end
         
     | 
| 
      
 240 
     | 
    
         
            +
                      options = options.except(:env)
         
     | 
| 
      
 241 
     | 
    
         
            +
                      Arql::App.instance.definitions[env_name].connection.drop_table(table_name, **options)
         
     | 
| 
       221 
242 
     | 
    
         
             
                    end
         
     | 
| 
       222 
243 
     | 
    
         | 
| 
       223 
244 
     | 
    
         
             
                    # Drops the join table specified by the given arguments.
         
     | 
| 
         @@ -227,7 +248,14 @@ module Arql 
     | 
|
| 
       227 
248 
     | 
    
         
             
                    # to provide one in a migration's +change+ method so it can be reverted.
         
     | 
| 
       228 
249 
     | 
    
         
             
                    # In that case, the block will be used by #create_join_table.
         
     | 
| 
       229 
250 
     | 
    
         
             
                    def drop_join_table(table_1, table_2, **options)
         
     | 
| 
       230 
     | 
    
         
            -
                       
     | 
| 
      
 251 
     | 
    
         
            +
                      env_name = options[:env]
         
     | 
| 
      
 252 
     | 
    
         
            +
                      unless env_name
         
     | 
| 
      
 253 
     | 
    
         
            +
                        raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
                        env_name = Arql::App.instance.environments.first
         
     | 
| 
      
 256 
     | 
    
         
            +
                      end
         
     | 
| 
      
 257 
     | 
    
         
            +
                      options = options.except(:env)
         
     | 
| 
      
 258 
     | 
    
         
            +
                      Arql::App.instance.definitions[env_name].connection.drop_join_table(table_1, table_2, **options)
         
     | 
| 
       231 
259 
     | 
    
         
             
                    end
         
     | 
| 
       232 
260 
     | 
    
         | 
| 
       233 
261 
     | 
    
         
             
                    # Renames a table.
         
     | 
| 
         @@ -235,9 +263,15 @@ module Arql 
     | 
|
| 
       235 
263 
     | 
    
         
             
                    #   rename_table('octopuses', 'octopi')
         
     | 
| 
       236 
264 
     | 
    
         
             
                    #
         
     | 
| 
       237 
265 
     | 
    
         
             
                    def rename_table(table_name, new_name)
         
     | 
| 
       238 
     | 
    
         
            -
                       
     | 
| 
       239 
     | 
    
         
            -
             
     | 
| 
      
 266 
     | 
    
         
            +
                      env_name = options[:env]
         
     | 
| 
      
 267 
     | 
    
         
            +
                      unless env_name
         
     | 
| 
      
 268 
     | 
    
         
            +
                        raise ArgumentError, ':env option is required' if Arql::App.instance.environments.size > 1
         
     | 
| 
       240 
269 
     | 
    
         | 
| 
      
 270 
     | 
    
         
            +
                        env_name = Arql::App.instance.environments.first
         
     | 
| 
      
 271 
     | 
    
         
            +
                      end
         
     | 
| 
      
 272 
     | 
    
         
            +
                      options = options.except(:env)
         
     | 
| 
      
 273 
     | 
    
         
            +
                      Arql::App.instance.definitions[env_name].connection.rename_table(table_name, new_name)
         
     | 
| 
      
 274 
     | 
    
         
            +
                    end
         
     | 
| 
       241 
275 
     | 
    
         
             
                  end
         
     | 
| 
       242 
276 
     | 
    
         
             
                end
         
     | 
| 
       243 
277 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,168 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Arql
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Extension
         
     | 
| 
      
 3 
     | 
    
         
            +
                extend ActiveSupport::Concern
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def v(compact: false)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  t = []
         
     | 
| 
      
 7 
     | 
    
         
            +
                  t << ['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']
         
     | 
| 
      
 8 
     | 
    
         
            +
                  t << nil
         
     | 
| 
      
 9 
     | 
    
         
            +
                  self.class.connection.columns(self.class.table_name).each do |column|
         
     | 
| 
      
 10 
     | 
    
         
            +
                    value = read_attribute(column.name)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    if compact && value.blank?
         
     | 
| 
      
 12 
     | 
    
         
            +
                      next
         
     | 
| 
      
 13 
     | 
    
         
            +
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
                    t << [column.name, value, column.sql_type, column.comment || '']
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  t
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def t(compact: false, format: :terminal)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  puts Terminal::Table.new { |t|
         
     | 
| 
      
 21 
     | 
    
         
            +
                    t.style = self.class.table_style_for_format(format)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    v(compact: compact).each { |row| t << (row || :separator) }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  }.try { |e|
         
     | 
| 
      
 24 
     | 
    
         
            +
                    case format
         
     | 
| 
      
 25 
     | 
    
         
            +
                    when :md
         
     | 
| 
      
 26 
     | 
    
         
            +
                      e.to_s.lines.map { |l| '  ' + l }.join
         
     | 
| 
      
 27 
     | 
    
         
            +
                    when :org
         
     | 
| 
      
 28 
     | 
    
         
            +
                      e.to_s.lines.map { |l| '  ' + l.gsub(/^\+|\+$/, '|') }.join
         
     | 
| 
      
 29 
     | 
    
         
            +
                    else
         
     | 
| 
      
 30 
     | 
    
         
            +
                      e.to_s
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  }
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def vd(compact: false)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  VD.new do |vd|
         
     | 
| 
      
 37 
     | 
    
         
            +
                    vd << ['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']
         
     | 
| 
      
 38 
     | 
    
         
            +
                    self.class.connection.columns(self.class.table_name).each do |column|
         
     | 
| 
      
 39 
     | 
    
         
            +
                      value = read_attribute(column.name)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      next if compact && value.blank?
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                      vd << [column.name, read_attribute(column.name), column.sql_type, column.comment || '']
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def to_insert_sql
         
     | 
| 
      
 48 
     | 
    
         
            +
                  self.class.to_insert_sql([self])
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def to_upsert_sql
         
     | 
| 
      
 52 
     | 
    
         
            +
                  self.class.to_upsert_sql([self])
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                def write_csv(filename, *fields, **options)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  [self].write_csv(filename, *fields, **options)
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def write_excel(filename, *fields, **options)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  [self].write_excel(filename, *fields, **options)
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                def dump(filename, batch_size=500)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  [self].dump(filename, batch_size)
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                included do
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                class_methods do
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  def v
         
     | 
| 
      
 73 
     | 
    
         
            +
                    t = [['PK', 'Name', 'SQL Type', 'Ruby Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']]
         
     | 
| 
      
 74 
     | 
    
         
            +
                    t << nil
         
     | 
| 
      
 75 
     | 
    
         
            +
                    columns.each do |column|
         
     | 
| 
      
 76 
     | 
    
         
            +
                      pk = if [connection.primary_key(table_name)].flatten.include?(column.name)
         
     | 
| 
      
 77 
     | 
    
         
            +
                             'Y'
         
     | 
| 
      
 78 
     | 
    
         
            +
                           else
         
     | 
| 
      
 79 
     | 
    
         
            +
                             ''
         
     | 
| 
      
 80 
     | 
    
         
            +
                           end
         
     | 
| 
      
 81 
     | 
    
         
            +
                      t << [pk, column.name, column.sql_type,
         
     | 
| 
      
 82 
     | 
    
         
            +
                            column.sql_type_metadata.type, column.sql_type_metadata.limit || '',
         
     | 
| 
      
 83 
     | 
    
         
            +
                            column.sql_type_metadata.precision || '', column.sql_type_metadata.scale || '', column.default || '',
         
     | 
| 
      
 84 
     | 
    
         
            +
                            column.null, column.comment || '']
         
     | 
| 
      
 85 
     | 
    
         
            +
                    end
         
     | 
| 
      
 86 
     | 
    
         
            +
                    t
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  def t(format: :terminal)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    heading_prefix = case format
         
     | 
| 
      
 91 
     | 
    
         
            +
                    when :md
         
     | 
| 
      
 92 
     | 
    
         
            +
                      '# '
         
     | 
| 
      
 93 
     | 
    
         
            +
                    when :org
         
     | 
| 
      
 94 
     | 
    
         
            +
                      '* '
         
     | 
| 
      
 95 
     | 
    
         
            +
                    when :sql
         
     | 
| 
      
 96 
     | 
    
         
            +
                      '-- '
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
      
 98 
     | 
    
         
            +
                    puts "\n#{heading_prefix}Table: #{table_name}\n\n"
         
     | 
| 
      
 99 
     | 
    
         
            +
                    if format == :sql
         
     | 
| 
      
 100 
     | 
    
         
            +
                      puts to_create_sql + ';'
         
     | 
| 
      
 101 
     | 
    
         
            +
                    else
         
     | 
| 
      
 102 
     | 
    
         
            +
                      puts(Terminal::Table.new { |t|
         
     | 
| 
      
 103 
     | 
    
         
            +
                        t.style = self.table_style_for_format(format)
         
     | 
| 
      
 104 
     | 
    
         
            +
                        v.each { |row| t << (row || :separator) }
         
     | 
| 
      
 105 
     | 
    
         
            +
                      }.try { |e|
         
     | 
| 
      
 106 
     | 
    
         
            +
                        case format
         
     | 
| 
      
 107 
     | 
    
         
            +
                        when :md
         
     | 
| 
      
 108 
     | 
    
         
            +
                          e.to_s.lines.map { |l| '  ' + l }.join
         
     | 
| 
      
 109 
     | 
    
         
            +
                        when :org
         
     | 
| 
      
 110 
     | 
    
         
            +
                          e.to_s.lines.map { |l| '  ' + l.gsub(/^\+|\+$/, '|') }.join
         
     | 
| 
      
 111 
     | 
    
         
            +
                        else
         
     | 
| 
      
 112 
     | 
    
         
            +
                          e.to_s
         
     | 
| 
      
 113 
     | 
    
         
            +
                        end
         
     | 
| 
      
 114 
     | 
    
         
            +
                      })
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  def vd
         
     | 
| 
      
 119 
     | 
    
         
            +
                    VD.new do |vd|
         
     | 
| 
      
 120 
     | 
    
         
            +
                      v.each do |row|
         
     | 
| 
      
 121 
     | 
    
         
            +
                        vd << row if row
         
     | 
| 
      
 122 
     | 
    
         
            +
                      end
         
     | 
| 
      
 123 
     | 
    
         
            +
                    end
         
     | 
| 
      
 124 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                  def to_insert_sql(records, batch_size=1)
         
     | 
| 
      
 128 
     | 
    
         
            +
                    to_sql(records, :skip, batch_size)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  def to_upsert_sql(records, batch_size=1)
         
     | 
| 
      
 132 
     | 
    
         
            +
                    to_sql(records, :update, batch_size)
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                  def to_sql(records, on_duplicate, batch_size)
         
     | 
| 
      
 136 
     | 
    
         
            +
                    records.in_groups_of(batch_size, false).map do |group|
         
     | 
| 
      
 137 
     | 
    
         
            +
                      ActiveRecord::InsertAll.new(self, group.map(&:attributes), on_duplicate: on_duplicate).send(:to_sql) + ';'
         
     | 
| 
      
 138 
     | 
    
         
            +
                    end.join("\n")
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  def to_create_sql
         
     | 
| 
      
 142 
     | 
    
         
            +
                    superclass.definition.connection.exec_query("show create table `#{table_name}`").rows.last.last
         
     | 
| 
      
 143 
     | 
    
         
            +
                  end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                  def dump(filename, no_create_table=false)
         
     | 
| 
      
 146 
     | 
    
         
            +
                    Arql::Mysqldump.new(superclass.definition.options).dump_table(filename, table_name, no_create_table)
         
     | 
| 
      
 147 
     | 
    
         
            +
                  end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                  def table_style_for_format(format)
         
     | 
| 
      
 150 
     | 
    
         
            +
                    case format.to_s
         
     | 
| 
      
 151 
     | 
    
         
            +
                    when 'md'
         
     | 
| 
      
 152 
     | 
    
         
            +
                      {
         
     | 
| 
      
 153 
     | 
    
         
            +
                        border_top: false,
         
     | 
| 
      
 154 
     | 
    
         
            +
                        border_bottom: false,
         
     | 
| 
      
 155 
     | 
    
         
            +
                        border_i: '|'
         
     | 
| 
      
 156 
     | 
    
         
            +
                      }
         
     | 
| 
      
 157 
     | 
    
         
            +
                    when 'org'
         
     | 
| 
      
 158 
     | 
    
         
            +
                      {
         
     | 
| 
      
 159 
     | 
    
         
            +
                        border_top: false,
         
     | 
| 
      
 160 
     | 
    
         
            +
                        border_bottom: false,
         
     | 
| 
      
 161 
     | 
    
         
            +
                      }
         
     | 
| 
      
 162 
     | 
    
         
            +
                    else
         
     | 
| 
      
 163 
     | 
    
         
            +
                      {}
         
     | 
| 
      
 164 
     | 
    
         
            +
                    end
         
     | 
| 
      
 165 
     | 
    
         
            +
                  end
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
              end
         
     | 
| 
      
 168 
     | 
    
         
            +
            end
         
     |