Arrayを継承したクラスの表示

Arrayだけハミ子なのねしらんかったしらんかった。というか汚い。

irb(main):001:0> module PTest
irb(main):002:1>  def to_s; "to_s" end
irb(main):003:1>  def inspect; "inspect" end
irb(main):004:1> end
=> nil
irb(main):005:0> class A ; include PTest end
=> A
irb(main):006:0> class B < Array; include PTest end
=> B

irb(main):007:0> p A.new
inspect
=> inspect
irb(main):008:0> p B.new
inspect
=> inspect

irb(main):009:0> puts A.new
to_s
=> nil
irb(main):010:0> puts B.new
=> nil

実際、1.9.3(2.1系でもいいんだけどif抜けて最適化されてるので判りにくい)のコードを見ると

VALUE
rb_io_puts(int argc, VALUE *argv, VALUE out)
{
    int i;
    VALUE line;

     :
     :
    for (i=0; i<argc; i++) {
    if (TYPE(argv[i]) == T_STRING) {
        line = argv[i];
        goto string;
    }
    line = rb_check_array_type(argv[i]);
    if (!NIL_P(line)) {
        rb_exec_recursive(io_puts_ary, line, out);
        continue;
    }
     :
     :
}

あー

いや何をしようとしてたかっていうと、連分数クラスをArray継承で作ってて、連分数表示をputsで出そうとしたらはまったという、、、
https://gist.github.com/tkuro11/5c96e0a94d822bf2f806
p つかうか、Arrayから継承あきらめるか。配列的に 連分数係数を指定できるのでいいと思ったんだけどなー

watchコマンドdiff表示をカラーに

久々の熱暴走した家鯖のモニタに また watchコマンド使ってたのですが
http://d.hatena.ne.jp/tkuro/20110519/1305753099
パッと見に上がってるのか下がってるのかわからんことがあったので色つけてみました。

ncursesの基本

  • initscr() でスタート
  • 色使うなら start_color()
  • ペア色にする場合は init_pairで作る。 init_pair(番号, foreground, background)
  • attron(...) で色つける。ペア参照はマクロ COLOR_PAIR(番号)が必要。

必要なのはこんなところかな

watchはどこに?

watchコマンドは procpsパッケージの中にあるらしい。

% apt-get source procps

で...
とりあえずキャラクタコードの大小で色を変えてみよう。

あててみた

diff --git a/watch.c b/watch.c
index 436d213..bdb2496 100644
--- a/watch.c
+++ b/watch.c
@@ -116,6 +116,9 @@ static void init_ansi_colors(void)

        for (i = 0; i < 8; i++)
                init_pair(i + 1, ncurses_colors[i], -1);
+
+       init_pair(10, COLOR_WHITE, COLOR_RED);
+       init_pair(11, COLOR_RED, COLOR_BLUE);
 }

 static void set_ansi_attribute(const int attrib)
@@ -493,6 +496,7 @@ static int run_command(char *restrict command, char **restrict command_argv)
                                exit_early = (unsigned char)c != oldc;
 #endif
                        }
+                       int attr_stands = 0;
                        if (flags & WATCH_DIFF) {
 #ifdef WITH_WATCH8BIT
                                cchar_t oldc;
@@ -511,16 +515,21 @@ static int run_command(char *restrict command, char **restrict command_argv)
                                        ((flags & WATCH_CUMUL)
                                         && (oldch & A_ATTRIBUTES)));
 #endif
+                               if (attr && (unsigned char)c > oldc) {
+                                       attr_stands = COLOR_PAIR(10);
+                               } else {
+                                       attr_stands = COLOR_PAIR(11);
+                               }
                        }
-                       if (attr)
-                               standout();
+                       if (attr)
+                               attron(attr_stands);
 #ifdef WITH_WATCH8BIT
                        addnwstr((wchar_t *) & c, 1);
 #else
                        addch(c);
 #endif
                        if (attr)
-                               standend();
+                               attroff(attr_stands);
 #ifdef WITH_WATCH8BIT
                        if (wcwidth(c) == 0) {
                                x--;

configure & make で新しい watch コマンドげとー

でけたあ

誰得?

微妙だw

まとめ

いらんことしてる場合じゃない

activesupport4.1.2のHash#deep_transform_keysとか

nested Arrayにも適用されるようになったとか。地味に便利かも

require "active_support/core_ext/hash/keys"

ahash = {
   :nested_array =>
      [
         { :a => 1, :c => 2},
         { :b => 3 }
      ]
}

transformed = ahash.deep_transform_keys { |key|
   (key.to_s + "_old").to_sym
}

p transformed

~ ➤ ruby -e "gem 'activesupport', '=4.1.1'; load 'a.rb'"
{:nested_array_old=>[{:a=>1, :c=>2}, {:b=>3}]}
~ ➤ ruby -e "gem 'activesupport', '=4.1.2'; load 'a.rb'"
{:nested_array_old=>[{:a_old=>1, :c_old=>2}, {:b_old=>3}]}

コード見る限りオフにはできないのかな。

GTDよ、もういちど。1日1ハックに向けて

どうも最近は余裕がない。余裕がないのでさらに仕事が進まない。仕事が進まないのでストレスがたまってさらに余裕がない。ハックもできない。というバカスパイラルをやってしまっていて、何がいけないんだろう?と悩み始める。

  1. 頭の回転速度が異常に落ちてる
  2. いつもドキドキしてる気がする
  3. 体調が慢性的に悪い
  4. 簡単な仕事が前よりも(感覚的に)異様に時間がかかる気がする(これは奥様に言わせると気のせいだそう)
  5. 意欲は結構あるが、夜起きてられないし朝早く起きられない

・・・・なんか年齢に応じた体調不良な気もするけれども、諦めてたまるか。
状況を考えてみた

人間もPCのようなもの

じっくり考えてみると以下のことに気が付く

  1. 後回しにしたままサボっている仕事が複数ある(仕事・プライベート両方)
  2. しかも解決の目途がたっていない
  3. 子供の世話で時間的余裕が非常に減っている
  4. 奥様も同様で余裕がなくなった結果、バカなミスが増えまくっている(もともとシステム化するのが苦手な人なので、、、)

心配事が増えてくるからそっちに頭がとられて回転速度が落ちて、結果として仕事が遅くなり、その結果後回し仕事がどんどん溜まって、しかも詳細忘れていくのでできなくなり、できないのでコワくなる。んで、結果ドキドキしてしまい、さらに考えることが増えて・・・といういわゆるGTDの本に必ず書いてある愚か者パターンだ!!!
後半は僕がコントロールできないが前二つはなんとかなるね。
まるでソフトをいろいろ入れた結果常駐ソフトだらけになって、動かないってわけではないのになんとなくうまく動いていない腐りかけのPCみたいだ。重いんだけど、入れなおすときのトラブルのリスクをおそれてそのままクリーンせずに放置して我慢して使い続けて効率激げーん、という状況だ。
多分、寿命も減る。

自分案件アンインストール開始!

というわけでいろいろ自己アンインストールして入れなおしたいと思う。
PCなら全部消してパーテ切りなおして、クリーンインストール、という手がある。PCは基本人間が刺激を与えてくれるので、別に「全部忘れて」も問題はない。全部忘れてからまた入れなおしてもらう、またはバックアップから再構成すればすむわけだ。
人間はそのままではそういうわけにはいかない。全部忘れてしまったら誰か(何か)にまた再教育してもらわなければならないわけで、本気でやるなら今までそれらに使った時間と同等の時間がかかってしまう。まあそこまで真剣に「忘れる」必要もないのだけれども。。。
そもそも忘れた情報はどこに? そう再インストールするためにはそれをもう一度完全に思い出せるように吐き出さなきゃいけない。
この

  1. バックアップを取る
  2. 忘れる(ここも重要かつ困難)
  3. 再インストールする
  4. 状態を維持する(メンテする)

GTDの基本、て本当にうまくまとまってるんだなー、とイマサラ思った。どれも時間かかりそう。
今まで本気で何時間も使って上記を一つ一つやったことは残念ながら無かった。どうしても家族が邪魔(失礼!)になってしまうので休日にはできないし、仕事のある時にやることもできない。
本気でやるなら、休みを取って、ホテルにでも泊まって、じっくり取り組むが正解な気がしてきた。そうだ。やってみよう。

いつやるかが問題だ

すぐにはできないですねぃ。ちゃーんと話し合って納得してもらってからじゃないと、今のまま一日家事育児*1休んだりすれば、奥様が破裂してしまう。家族がいるのは何にもまして力ではあるんだけど、やはり制約でもあるのですよねっ(って誰に言ってるんでしょ)。
なんとかして、とりあえず目標は頭の中のごちゃごちゃ払い出して一日1つ新しいことを学べるくらいに戻そう。まずは一日1時間自分の時間を(夫婦共に)取れるようにしよう。

という、おっさんの遅すぎる決意表明でした。
ついでに全部終わったらはてなブログに移行しよう。

*1:子供がおおきくなれば、妻が優秀なら・・・ってのはおそらくうまくいかないパターン

PUT|DELETEメソッドの謎

いままで全く気にしてもいなかったんだけど、Railsのlink_toて<a>タグ作ってるはずなのに、methodが指定できるのがふと不思議になってきました。どうなってんのでしょう?

まずはソース

生成されたソース見てみると

<a href="/icode/3" data-confirm="really delete?" data-method="delete" rel="nofollow">delete</a>

みたいな感じ。

「rel="nofollow"」は、「このページのリンクをたどらない」や「このリンクをたどらない」といった指示を検索エンジンに与える手段の 1 つ,

だ、そうなので、なんぞ data-methodのとこか。data-*ってのはHTML5のカスタム属性で、JSから*.datasetで簡単に取れます。
http://tokkono.cute.coocan.jp/blog/slow/index.php/xhtmlcss/html5-data-attributes-vs-jquery-data-api/
ここに詳しく載ってました。感謝。多謝。雨霰。
ともかく犯人はjsだよなとWeb inspector起動。

ここです。

    $(document).delegate(rails.linkClickSelector, 'click.rails', function(e) {
      var link = $(this), method = link.data('method'), data = link.data('params');
          :
      if (link.data('remote') !== undefined) {
          :
      } else if (link.data('method')) {
        rails.handleMethod(link);
        return false;
      }
    });

これだね。

    handleMethod: function(link) {
      var href = rails.href(link),
        method = link.data('method'),
        target = link.attr('target'),
        csrf_token = $('meta[name=csrf-token]').attr('content'),
        csrf_param = $('meta[name=csrf-param]').attr('content'),
        form = $('<form method="post" action="' + href + '"></form>'),
        metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';

      if (csrf_param !== undefined && csrf_token !== undefined) {
        metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
      }

      if (target) { form.attr('target', target); }

      form.hide().append(metadata_input).appendTo('body');
      form.submit();
    },

うわーすごい。hidden formを生成して submitしてるのね。しかしformのmethodは"post"。hiddenで _methodを投げてるというへんてこ状態。なぜ?

なぜにpost??

というのは単純にブラウザ*1が PUT, DELETEなどに対応していない(サーバー側でも LIMITしている可能性がある)から、という認識であってるのかな。ともかくこういう動作をしているらしい。なんとなくRESTできれいなイメージで動いているものとばかり思っていたので騙されたような気持ち悪い感覚。やだなあ。
という訳で、RailsではRESTfulっぽくみせる疑似RESTになっている、というところまで理解した。
なるほど。

結論

とっととRESTに全移行しちゃって!!!*2

*1:正確にはHTMLの仕様.HTML5でも同様

*2:ブラウザというかHTMLの問題だけなので移行してない訳じゃないけども。しかしなぜHTML側でRESTな方向に行ってないんだろう? この辺り弱いっす・・・

今日の名言7

風邪で死んでて一日抜けてしまった。

Remember that time is money.
- Benjamin Franklin : Advice to a Young Tradesman

著者はアクセク働くのが美徳、な常識の中で育った方なので、それに対するアンチテーゼで、「この言葉を老いてなお使うのは貧困」という結論を持ってらしたけど、それは「人生=仕事」という変な思い込みのせいだと思う。実際 時は金以上のもの、なのだ。過ぎた時間は絶対に買えないしね。