ruby まあまあ使う自作のメソッドをまとめたメモ

モジュールは適当にrequireする。ruby ver = 2.5.0
ネーミングセンスは皆無なのでアドバイス希望。
より良い書き方のアドバイスも希望。

### hashをjson形式でファイル出力するやつ

```ruby
  def dump_hash2json(filename, hash, writetype = 'w')
    File.open(filename, writetype) do |file|
      JSON.dump(hash, file)
    end
  end
```

### json形式のファイルをhashとして読み込むやつ

```ruby
  def load_json2hash(filename)
    File.open(filename) do |file|
      JSON.load(file)
    end
  end
```

### 配列をcsv形式でファイル出力する

```ruby
  def dump_csv(filename, writedata, writetype = 'w')
    CSV.open(filename.dup, writetype) do |csv|
      writedata.each do |arr|
        csv << [arr]
      end
    end
  end
```

### ディレクトリ内の正規表現にマッチしたファイル名を取得するやつ

```ruby
  def get_filenames_matching_regexp(dirpath, regexp)
    Dir.open(dirpath).to_a.grep(/#{regexp}/)
  end
```

### 外部コマンド実行

```ruby
  def mypopen3(cmd)
    Open3.popen3(cmd) do |_stdin, stdout, stderr, _wait_thr|
      begin
        loop do
          IO.select([stdout, stderr]).flatten.compact.each do |io|
            io.each do |line|
              puts line
            end
          end
          break if stdout.eof? && stderr.eof?
        end
      end
    rescue EOFError
    end
  end
```

### ファイル削除

inputinfoがstringかarrayかで処理を分けている

```ruby
  def mydisplay(level, arg)
    puts "#{level}: #{mytime} #{arg}"
  end

  def mytime
    tm = Time.now
    tm.strftime('%Y-%m-%dT%H:%M:%S.%6N')
  end

  def rmv_files(inputinfo, dirpath = './')
    mydisplay('INFO', "removing.. #{dirpath}, #{inputinfo}")
    intype = inputinfo.class
    if intype == String
      FileUtils.rm_f(Dir.glob("#{dirpath}/#{inputinfo}"))
    elsif intype == Array
      if inputinfo.is_a?(Array)
        inputinfo.map! { |v| FileUtils.rm_f(Dir.glob("#{dirpath}/#{v}")) }
      end
    end
  end
```

### ファイル移動

```ruby 
  def mv_file(path_from, path_to)
    FileUtils.mv(Dir.glob(path_from), path_to)
  end
```

### ファイルに追加

```ruby
  def add_file(filename, message)
    mydisplay('INFO', "adding.. #{filename}")
    File.open(filename, 'a') do |f|
      f.puts(message)
    end
  end
```

### ディレクトリ作成

```ruby
  def create_dir(dirpath)
    FileUtils.mkdir_p(dirpath, mode: 755)
  end
```

### zip解凍

```ruby
  def uncompress(path, outpath)
    entrys = []
    mydisplay('INFO', "unzipping.. #{path}")
    Dir.mkdir(outpath) unless Dir.exist?(outpath)
    Zip::InputStream.open(path, 0) do |input|
      while (entry = input.get_next_entry)
        save_path = File.join(outpath, entry.name)
        File.open(save_path, 'w') do |wf|
          wf.puts(input.read)
        end
        entrys << save_path
      end
    end
    entrys
  end
```

### 入れ子のhashから値をとってくるやつ

```ruby
require 'active_support'
require 'active_support/core_ext'

class Hash
  def get_nested_value(str)
    keys = str.split(',')
    v = self.with_indifferent_access # need active_support
    keys.each do |i|
      v = v[i.to_s]
    end
    v
  end
end

hash = {a: "test", "b": {c: "testtest", d: {e: "testtesttest"}}}

p hash.get_nested_value('a')
p hash.get_nested_value('b,c')
p hash.get_nested_value('b,d,e')
```

### ymlの設定ファイルを読み込むやつ

```ruby
  def load_yml_settings(path)
    Hashie::Mash.load("#{path}")
  end
```

### postgres操作のなんやかんや
以下の例は環境変数から設定を読み込んでいるので適宜変える。
\copyなどは\のせいで使えなかった。

```ruby
  def myconnection
    dbhost = ENV['DB_HOST']
    dbuser = ENV['DB_USER']
    dbpass = ENV['DB_PASS']
    dbname = ENV['DB_DBNAME']
    dbport = ENV['DB_PORT']
    connection = PG.connect(host: dbhost,
                            user: dbuser,
                            password: dbpass,
                            dbname: dbname,
                            port: dbport)
    mydisplay('INFO', "DB_CONNECT: #{dbuser}@#{dbhost}:#{dbport} #{dbname}")

    connection.exec('START TRANSACTION ISOLATION LEVEL READ COMMITTED;')
    #connection.exec('SAVEPOINT test001;')
    mydisplay('INFO', "TRANSACTION_STATUS: #{connection.transaction_status}")
    connection
  end

  def endconnection(con)
    mydisplay('INFO', 'DB_CONNECT_END:')
    con.exec('COMMIT;')
  end

  def abortconnection(con)
    mydisplay('INFO', 'DB_ROLLBACK: TRANSACTION ERROR.')
    con.exec("ROLLBACK;")
    #con.exec('ROLLBACK TO test001;')
  end

  def insert_cmd(con, table, head, value)
    cmd = %(insert into #{table}
               #{head}
             values
               (#{value});
    )
    begin
      mydisplay('INFO', "DB_EXEC: #{cmd}")
      con.exec(cmd)
    rescue StandardError => e
      mydisplay('ERR!', "DB INSERT FAILED #{e.backtrace}")
      abortconnection(con)
      add_file("#{ENV['DB_LOG']}/DBERRINFO", e.backtrace.to_s)
      exit 1
    end
  end

  # 配列の各要素をシングルクォーテーションで囲わないとエラーが出た。。
  def get_value_for_insert_db(arr)
    arr.map { |v| "'#{v}'" }.join(', ')
  end
  
  def get_latest_id(con, table, idname)
    cmd = "select MAX(#{idname}) from #{table}"
    begin
      mydisplay('INFO', "DB_EXEC: #{cmd}")
      rslt = con.exec(cmd)
      return rslt.max.values.join('')
    rescue StandardError => e
      mydisplay('ERR!', "GET ID FAILED #{e.backtrace}")
      abortconnection(con)
      add_file("#{ENV['DB_LOG']}/DBERRINFO", e.backtrace.to_s)
      exit 1
    end
  end

  # テーブルinsertの例
  def insert_test(dbcon, yml, arr)
    table = "#{yml.test[0]}"
    tmp = ['id001','test','hogehoge']
    value = get_value_for_insert_db(tmp)
        insert_cmd(dbcon, table, yml.test[1], value)
      end
    end
  end

  # ymlの例
  # test: ["test_table","(id, testname, contents)"]
  # ...

```