コピペコードで快適生活

明日使えるソースを自分のために

Rubyのinclude,extend,prepend,Concernの使い方メモ

なんとなく理解が怪しかったので復習をかねて。

includeだけでクラスメソッドとインスタンスメソッドを同時に追加する

module MyModule
  def self.included(base)
    base.extend(ClassMethods)
  end
 
  module ClassMethods
    def hogehoge
      puts 'hogehoge!'
    end
  end
 
  def fugafuga
    puts 'fugafuga'
  end
end

class TargetModel
  include MyModule

  # 略
end

・includeは、モジュールのメソッドをインスタンスメソッドとして追加する。
・extendは、レシーバ自身に対してメソッドを追加する。
 クラス.extend モジュール の場合はクラスメソッドとして
 インスタンス.extend モジュール の場合はインスタンスメソッドとして追加される。
・モジュールにincludedを定義しておくと、includeされたときに呼び出される。
 引数はincludeを行ったクラスやモジュール。

ActiveSupport::Concernを使う場合

require 'active_support/concern'
module ConsernModule
  extend ActiveSupport::Concern

  # インスタンスメソッドとして使える
  def hogehoge
    # do something
  end 

 # アクセサやscopeの定義はincludedの中で行う
  included do
    attr_accessor :fugafuga
    scope :favorites, -> { where(favirite_flag: true) }
  end

  # クラスメソッドの定義はclass_methodsの中で行う
  class_methods do
    def piyopiyo
      # do something
    end
  end

  # privateインスタンスメソッド
  private
  def wiblewible
    # do something
  end
end

class TargetModel
  include ConsernModule

  # 略
end

prependを使う

module TargetModelPatch
  def self.prepended(base)
    base.extend(ClassMethods)

    base.has_many :childrens
    base.scope :without_deleted, { where(deleted_at: nil) }
  end
 
  module ClassMethods
    def hogehoge
      puts 'hogehoge!'
    end
  end
 
  def fugafuga
    puts 'fugafuga'
  end
end

TargetModel.prepend TargetModelPatch

includeと基本的な動きは同じだけど、同じメソッドがあった場合はモジュール側のメソッドで上書きになる。
これは、prependが継承チェインの「先頭」にモジュールを差し込むため。
なお、includeの場合は取り込んだクラス側のメソッドが優先になる。


※参考にさせていただきました。
いつも忘れるRubyの include, prepend, extend の意味。そしてActiveSupport::Concernについても。 - Qiita
www.techscore.com

screenコマンドメモ

本番サーバで手動でバッチをまわしたけど、sshのセッションが切れて「あぁぁぁぁ」って、状況にしたくないときとかに使う。

セッションを作る

screen

デタッチする

<ctrl> + <a> おしてから d

セッション一覧

screen -ls

アタッチする

screen -r 
screen -r セッションID

screen内でスクロール

[CTRL]+[A] + [ESC] でモード切替して ↑↓で移動
もう一度、[ESC] 押すとモード戻る。

package.jsonで読み込み先を指定してインストール

たまにしか使わなくてよく忘れるのでメモ。

リポジトリ向ける

{
  "name": "app",
  "version": "0.0.1",
  "description": "app",
  "author": "kinosuke",
  "dependencies": {
    "common": "git+ssh://git@github.com:account/rep.git#branch"
  }
}

ローカル向ける

{
  "name": "app",
  "version": "0.0.1",
  "description": "app",
  "author": "kinosuke",
  "dependencies": {
    "common": "../rep"
  }
}

SJISのCSVからシェルで集計するまでの流れ

CSVのデータを集計を、シェルでさくっと終わらせたいときのためのメモです。

まずは文字コードを変換

だいたいCSVSJISであることが多いので、シェルで正しく処理できるようにUTF-8に変換します。

# 使える文字コード一覧
iconv -l

# f(from)の文字コード
# t(to)の文字コード
iconv -f SJIS -t UTF8 target.csv > _target.csv

tsvに変換する

CSVは扱いづらいのでタブ区切りに変換します。

# csv2tsv.rb
require 'csv'

fn = ARGV[0]

if fn.nil?
  puts "CSVファイル名を指定してください" 
  exit
elsif File.extname(fn) != ".csv"
  puts "CSVファイルを指定してください" 
  exit
end

fw = File.open("#{File.basename(fn, '.csv')}.tsv", 'w')
CSV.foreach(fn, 'r') do |row|
  fw.puts(row.join("\t"))
end
fw.close

puts 'created tsv_file'

実行

ruby csv2tsv.rb target.csv

awkで集計する

# 9列目が特定の値の行だけ出力
cat *.gz | gzip -dc | gawk '{if ($9 >= 500) print $0};'

# 12列目をsumして出力
cat target.tsv | gawk -F"\t" '{s += $12} END {print s}'

# 10列目でグルーピングして、12列目をsumして出力
cat target.tsv | gawk -F"\t" '
{
  count[$10]+=1
  sum[$10]+=$12
};
END {
  for (key in sum) {
    print key, count[key], sum[key]
  }
}
'