ttyとptsについて

dokcer runのオプションで意味不明だったので、調べていました。

docker run -it ←こいつ

  % docker run --help
  -i, --interactive                    Keep STDIN open even if not attached
  -t, --tty                            Allocate a pseudo-TTY

ここでTTYが出てきました。

TTYとは

ttyとは、標準入出力となっている端末デバイス(制御端末、controlling terminal)の名前を表示するUnix系のコマンドである。 元来ttyとはteletypewriter(テレタイプライター)のことを指す。

tty - Wikipedia

ターミナルで打つとこうなります。

  % tty
/dev/ttys004

実際にターミナルで打っている端末の情報ですね。

よくある遊びです。

ここでターミナルを別のウィンドウで立ち上げます。

  % tty  ←ターミナル1
/dev/ttys004

  % tty  ←ターミナル2
/dev/ttys006

ターミナル1のウィンドウから下記コマンドを実行する

% echo "Hello tty" > /dev/ttys006

  % Hello tty←ターミナル2

これを実験するとどういうものかわかりやすいと思います。

pts

ptsはsshでログインした時の端末の情報です。

tty
/dev/pts/0

ということは、誰かがsshで同時接続していた場合に、相手をびっくりさせることができますね。

【参考】

d.hatena.ne.jp

ローカル環境のURLをlocalhost以外にする方法

localhostってださいなって思う時があるじゃないですか?

そんな時に名前をhostを変える方法です。

/etc/hostsがあると思います。

この設定ファイルに付け足します。

127.0.0.1 foo.com

これでrails sするとhttp:foo.com:3000でアクセスできます。

:3000がいるのはポートの関係ですね。

こうすると、「こいつわかってるやつじゃね?」って感じられそう。

以上です。

CSVでファイルを保存するなら、jsonで保存する方が楽ということに気づいた

CSVでhashの値を保存する場合分解しないといけないじゃないですか?

めんどくさいですよね。

例えばこういうデータです。

class FooApi
  HEADER = %w(foo bar baz)

  def export
    CSV.open('foo.csv', 'w:utf-8', headers: HEADERS, write_headers: true, force_quotes: true) do |csv|
      results.each do |result|
        line = [
          result[:foo],
          result[:bar],
          result[:baz]
        ]
        csv.puts line
      end
    end
  end

  private

  def results
    [ {
        foo: 1,
        bar: 2,
        baz: [1, 2]
      },
      {
        foo: 3,
        bar: 4,
        baz: [3, 4]
      },
    ]
  end
end

これよりももっとカラムが増えることなんて多いですよ。

HEADERとか考えるのめんどくさいなって思いました。

そこでjsonで書き出せば何も考えなくていいことに気づきました。

  def export
    FIle.open('foo.json', 'w') { |f| f.puts results }
  end

これで全てが終わります。

  def import
    @x = open('foo.json') {|f| JSON.load(f)}
  end

JSONの場合、keyがStringになって嫌だ!ってことがあると思います。

そんな時のためのwith_indifferent_accessです。

ActiveSupport頼みになりますが、これでアクセスできるようになります。

  @x.map!(&:with_indiffrent)access)

もちろん、クライアントによってはjsonって何?ってお客さんも多いでしょう。

ただ、自分の作業やjsonの意味がわかる人なら、ガンガン使うべきだなって思いました。

以上です。

正規表現で〜から〜までのパターン

こういうやつです。

宮藤官九郎(第1話、第2話、最終話)で名前と後ろを分けたい場合。

(?<name>.[^((]*)(?<supplement>.*)?

否定を間に挟んで、それ以外までにする。

これがミソ。

このパターン多いと思うし、覚えておこ。

正規表現で名前付きキャプチャが便利だった

これがあれば何にマッチさせているかわかるじゃん!って感動しました。

正規表現でキャプチャするときに$1で変数格納されますが、この場合何にマッチさせているのかがわかりづらいときがあります。 何より量が増えてくるとしんどいです。

使い方

(?<name>正規表現を書いてください)

サンプルです。

text =  ["塚本連平(MMJ)", "小松隆志(MMJ)", "六車俊治(テレビ朝日)"]
text.split(/\s/).map do |director|
  m = director.match(/(?<name>.*)(?<organization>.*)/)
  {
    name: m[:name],
    organization: m[:organization]
  }
end

=> [{:name=>"塚本連平", :organization=>"(MMJ)"}, {:name=>"小松隆志", :organization=>"(MMJ)"}, {:name=>"六車俊治", :organization=>"(テレビ朝日)"}]

何をやっているのかがわかりやすいです。

$1 よりも圧倒的にやりやすい。

今後とも使っていきます。

rubyでeach_with_indexでindexの値を0以外から始める方法

rubyでeach x indexをしたいパターンが多いです。

そのために、each_with_indexというメソッドがあります。

each_with_index

こちらは基本的に初期値が0からになります。

array = %w(foo bar baz)
array.each_with_index do |x, index|
  puts "#{index}番目#{x}"
end

=>
0番目foo
1番目bar
2番目baz

1から始めたいという場合は、下記のようにすることで回避できます。

array = %w(foo bar baz)
array.each_with_index do |x, index|
  puts "#{index + 1}番目#{x}"
end

=>
1番目foo
2番目bar
3番目baz

ただ、いちいち+ nを書かないといけないので、めんどくさいです。

each.with_index

そこで、each.with_indexを使用します。

こちらは()を入れることで開始位置を指定できます。

array = %w(foo bar baz)
array.each.with_index(1) do |x, index|
  puts "#{index}番目#{x}"
end
=>
1番目foo
2番目bar
3番目baz

まとめ

indexを0から始める場合は、each_with_index 0以外から始める場合は、each.with_index(n)をするのがいいのかなと個人的には思いました。

ActiveModelでcallbackをする方法

Formオブジェクトを使用していて、まともにActiveModelを使用しました。

ActiveRecordの場合は自動的にcallbackを仕込めるのですが、ActiveModelの場合はどうすればいいのかわからなかったです。

使い方

class WorkForm
  include ActiveModel::Model
  define_model_callbacks :save←callbackを定義する

  before_save :valid_resource←callbackのメソッドを作成する

  def save
    run_callbacks :save do←使用する場所を書く
    ...
    end
  end


  private

  def valid_resource
     ...←処理を書く
  end
end

公式に書いてあります。

ActiveModel::Callbacks

以上です。

rails5でautoload問題を解決する

やられましたよ。

rails4 → rails5へのアップデートをしていたのですが、libpathの配下のものが読まれない。

config/application.rb

    config.autoload_paths += %W(#{config.root}/lib)

問題ないだろ。

そう思っていましたよ。

どうやら、この作業が無効になっています。

2.6 production 環境での起動後は自動読み込みが無効になる 今後Railsがproduction 環境で起動されると、自動読み込みがデフォルトで無効になります。

アプリケーションの一括読み込み(eager loading)は起動プロセスに含まれています。このため、トップレベルの定数についてはファイルをrequireしなくても問題なく利用でき、従来と同様に自動読み込みされます。

トップレベルより下で、実行時にのみ有効にする定数(通常のメソッド本体など)を定義した場合も、起動時に一括読み込みされるので問題なく利用できます。

ほとんどのアプリケーションでは、この変更に関して特別な対応は不要です。めったにないと思われますが、productionモードで動作するアプリケーションで自動読み込みが必要な場合は、Rails.application.config.enable_dependency_loadingをtrueに設定してください。

Rails アップグレードガイド | Rails ガイド

ほとんどのアプリケーションでは、この変更に関して特別な対応は不要です。

いや、だいぶ影響あるだろ。

みんな使ってますよ!

ということで解決策

config.enable_dependency_loading = true

これはアップグレードガイドに書いていますね。

他にもやり方があります。

参考

qiita.com

危ない危ない・・・。

nodeのメモリー足らない問題をswapで回避する

AWSのt2.microだと、メモリーが1Gです。

webpackerを使用していると、普通にdeployで落ちてしまいます。

FATAL ERROR: JS Allocation failed - process out of memory
Aborted

こんな感じのエラーが出てにっちもさっちもいかなかったです。

memoryが足らないと言うことで、memoryを増やせばいいのですが、無料期間なので、グレードをあげて対処するなんてもったいないです。

どうしよう・・・っと思っていたところに、swap領域を作れば回避できるんじゃないですか?とアドバイスをいただいたので、swap領域を作成することにした。

AWSの上位インスタンスだと、最初からswapはあるようだけど、安いインスタンスだとなかった。

あと、inuxだと、swap領域を自分で設定できたとは知らなかった。

swapとは

HDDにメモリー領域を作成して、高速にアクセスできるようにします。 パソコンはメモリー上にある領域は高速にアクセスできるのですが、HDDに書き込みするのは遅いです。 ということで、memoryが足らない状態になると、HDDにメモリー領域を作成します。

今回は実際のメモリー上のアクセスしかしていなくて、メモリー領域が足らなくて落ちていました。

コマンド

sudo dd if=/dev/zero of=/swap bs=1M count=1024
sudo mkswap /swap
sudo swapon /swap

んで、freeコマンドで確認する。

Mem:       1022936     831780     191156       1592      80336     183480
-/+ buffers/cache:     567964     454972
Swap:      1048572      10064    1038508

無事にできている。

topコマンドでもきちんと作成されています。

top - 21:06:59 up 1 day, 21:51,  1 user,  load average: 0.00, 0.05, 0.14
Tasks:  64 total,   1 running,  63 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.7 us,  0.1 sy,  0.0 ni, 98.3 id,  0.9 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:   1022936 total,   832076 used,   190860 free,    80336 buffers
KiB Swap:  1048572 total,    10064 used,  1038508 free.   183504 cached Mem

きちんとコンピューターの仕組みがわかれば大した問題じゃないのですが、解決できてよかった。

意外にサーバー面白い!

gitのリポジトリの中で、issueのURLを開くコマンドを作成した

いちいちgitを開けるのが面倒くさいってパターンです。

#!/usr/bin/env ruby

require 'open-uri'

url = "https://github.com/foo/bar/issues/#{ARGV.first}"

system "open #{url}"

ファイル名をbin/issueで登録する。

bin/issue 10

これで開きます。

もう少しいい書き方がありそう。

面倒くさいので、ターミナルからブラウザを開く行動までやっていきたいですね。