Home > Perl Archive

[ << < 6  7  8  9  10  11  12  13  14  15  16 >> ]

Perl Archive

よく使うコマンド

みんながやっている時にやらないのがひねくれ者の真骨頂。日常よく使っている系を history から抜き出してみた

クライアントマシン

  • 無差別
 86 l
 66 dream
 62 cd
 39 for
 29 ssh-agent
 28 ssh-add
 28 jobs
 21 oneroad
 21 myrsync
 18 gcp
  • 除 alias や自前コマンド
 62 cd
 39 for
 29 ssh-agent
 28 ssh-add
 28 jobs
 16 clear
 11 curl
 10 open
  8 mkdir
  7 tar

サーバマシン

  • 無差別
197 fg
173 perl
 44 l
 17 jobs
  9 vim
  8 w3m
  8 rm
  8 emacs
  5 clear
  4 mv
  • 除 alias や自前コマンド
197 fg
173 perl
 17 jobs
  9 vim
  8 w3m
  8 rm
  8 emacs
  5 clear
  4 mv
  4 ls

クライアントマシンとサーバマシンの傾向がはっきりしていておもしろかった
あと、長めなのに手入力しているやつは、頭では覚えていないのに手が覚えているらしくておもしろかったので、書き残しておく

※長いのは読みやすいように複数行に分けた

tar zcfvp - target_dir | ssh user@host "cat > target.tar.gz"
tar zcfvp - target_dir | ssh user@host "tar zxfvp -"
zcat access.log.yyyymmdd.gz|awk '{print $1}'|sort|uniq -c|sort -nr|head -10
for i in `ls`;do cp $i $i.org;done
for i in dir1 dir2 dir3
do rsync -avvz --delete -e ssh user@host:~/data/$i ~/data
done

実際は、手が覚えてるんじゃなくて、常に History から使ってるんだけどね

フレームワーク (8) - サブクラスでのメソッドのオーバーライドを禁止する

C::M::App は、CGI::Application と同様、自分のクラスから継承されることを想定している

package MyClass;
use basee 'CGI::Minimal::App';

1;

んだが、一部メソッドは子クラスでのオーバーライド前提だし、一部メソッドはオーバーライドされたくないし、ということで、思案。他の言語みたいに attribute :final とか用意されてると

sub cannot_override :final {
}

とかするだけだし、そういうことを行うモジュール Attribute::Final もあるんだが、外部モジュール使うほどでもないし、attribute で実装しなくてもよかろう

# 子クラスの時だけ実行
unless ( ref $self eq __PACKAGE__ ) {
  for my $method (@all_methods) {
    next if .... ; # 親クラスのメソッドだったら何もしない

    die 'You can NOT OVERRIDE method'
      if ( grep {$_ eq $method} @not_override_methods );
  }
}

まずは基本ということで、Class::Inspector 使ってみる

# Check methods that cannot override in Sub-Class
unless ( ref $self eq __PACKAGE__ ) {
  my @not_override_methods = qw(
                                new run
                                _tt_obj _setup_http_headers _lvalue_method
                               );
  for my $method ( @{Class::Inspector->methods(ref $self, 'expanded') || [[]]} ) {
    next if $method->[1] eq __PACKAGE__;
    die 'You can NOT OVERRIDE method ',__PACKAGE__,'::',$method->[2],' in ',$method->[1]
      if ( grep {$_ eq $method->[2]} @not_override_methods );
  }
}

続いて、Class::Inspector はコアモジュールではないので、使わない版

# Check methods that cannot override in Sub-Class
unless ( ref $self eq __PACKAGE__ ) {
  my @not_override_methods = qw(
                                new run
                                _tt_obj _setup_http_headers _lvalue_method
                               );
  {
     no strict 'refs';
     for my $method ( keys %{ref($self).'::'} ) {
       next unless defined &{ref($self).'::'.$method};
       die 'You can NOT OVERRIDE method ',__PACKAGE__,'::',$method,' in ',ref($self)
         if ( grep {$_ eq $method} @not_override_methods );
     }
  }
}

タイムリーなことに、「どう書く?org」で「メソッド名一覧の表示」がお題になっているので、良さげな回答がでてきたらマネさせてもらおう

で、この実装だとコンストラクタ生成後にチェックするので、use した時点でチェクする方法考えた方がいいのかなぁ、とちょっと思った。new のしょっぱなにやっとけば同じかな

フレームワーク (7) - lvalue で validation もしたい - その2 -

もっとスマートな実装方法はないものか

って、絶対あるはず。Class::Accessor::Lvalue とかあるんじゃね? と思ったら、やっぱりあった。速度比較とかしているこんなサイトも見つけた

楽々アクセサ生成だけならどれでもできそうだが、今回の要件を満たすかどうかはわからないので、後日勉強するということで。つうか、lvalue やめればシンプルになりますな

フレームワーク (6) - lvalue で validation もしたい

header_type というメソッドを実装していた時のこと。

package CGI::Minimal::App;
sub header_type :lvalue {
  my $self = shift;
  $self->{__HEADER_TYPE};
}

これで

  • $self->header_type('redirect');
  • $self->header_type = 'redirect';

どちらの書き方でも setter として動作し、$self->header_type は getter にもなる。が、header_type に set できる値は制限したいので、

package CGI::Minimal::App;
sub header_type :lvalue {
  my $self = shift;
  my $type = shift;

  die 'Invalid header type: '.$type
    unless ( $type eq 'header' or $type eq 'redirect' );

  $self->{__HEADER_TYPE} = $type;

  $self->{__HEADER_TYPE};
}

というようなコードを書くと、

$self->header_type('dummy');

はエラーになるが

$self->header_type = 'dummy';

はエラーにならない

lvalue の時も validation のロジックを通したいので、しばし思案。結果、tie を使うことにした。動いてるけど。。。もっとスマートな実装方法はないものか

package CGI::Minimal::App;
sub header_type :lvalue {
  my $self = shift;
  my $header_type = shift;

  # First use? Create new __HEADER_TYPE!
  $self->{__HEADER_TYPE} = 'header' unless exists $self->{__HEADER_TYPE};

  # tie getter and setter to CGI::Minima::App::Magic (to validate)
  tie $self->{__HEADER_TYPE}, 'CGI::Minimal::App::Magic', $self,
    sub {
      my $self = shift;
      $self->{__HEADER_TYPE};
    },
    sub {
      my $self = shift;
      my $value = shift;

      # check allowed header
      die 'Invalid header type: '.$value
        unless ( grep {$_ eq lc($value)} ('header', 'redirect', 'not_found', 'not_modified', 'none') );
      $self->{__HEADER_TYPE} = lc($value);
    };

  $self->{__HEADER_TYPE} = $header_type if defined $header_type;
  $self->{__HEADER_TYPE};
}
1;

package CGI::Minimal::App::Magic;
sub TIESCALAR {
  my $class = shift;
  my $self = shift;
  my $getter = shift;
  my $setter = shift;

  $class = ref $class || $class || __PACKAGE__;
  bless({obj => $self, getter => $getter, setter => $setter}, $class);
}

sub FETCH {
  my $self = shift;
  $self->{getter}->($self->{obj});
}

sub STORE {
  my $self = shift;
  my $value = shift;

  $self->{setter}->($self->{obj}, $value);
}
1;

フレームワーク (5) - 最低限の実装完了。。。したけど

最低限の実装は完了した。。。が、このまま作り続けていくと「CGI::Application じゃあかんの? 自分用のラッパ書いたらええやん」ということになりそうな香りがプンプンと。。。そんだけ CGI::Application がよくできてるってことだなぁ

シンプルなものが欲しいはずなのに、なぜ欲張ってしまうかというと「公開」と「汎用性」が気になるから。そして、書き始めるといろんなこと試したくなるから。趣味でやってると欲にキリがなくなるので、ひとまず「融通きかなくて俺しか使えないぜベイベー」仕様を意識

フレームワーク (4) - 枠組み完成

大枠できた。簡単なコマンドラインアプリは作れるレベル

  • PATH_INFO or QUERY_STRING で実行するメソッド振り分ける部分できた
  • REQUEST_METHOD で実行するメソッド振り分ける部分できた
  • TT 使う部分は未実装だが、構想はまとまった
  • HTTP header をあつかう部分を構想中
  • CGI::Minimal の全機能使いたいかなぁ。。。と思案中
  • mod_perl とか fcgi とかについて思案中

フレームワーク (3) - $obj->query() と $obj->param()

package CGI::Minimal::App;

use strict;
use warnings;

use UNIVERSAL::require;

sub query {
    my $self = shift;
    my $query = shift;

    # If query object is not exist, set a new query object.
    unless ( exists $self->{__QUERY_OBJ} ) {
        if ( defined $query ) {
            $self->{__QUERY_OBJ} = $query;
        }
        else {
            my $module = 'CGI::Minimal';
            unless ( exists $INC{$module} ) {
                $module->require or die $!;
            }
            $self->{__QUERY_OBJ} = $module->new();
        }
    }
    return $self->{__QUERY_OBJ};
}

sub param : lvalue {
    my $self = shift;
    my @data = @_;

    # First use? Create new __PARAMS!
    $self->{__PARAMS} = {} unless exists $self->{__PARAMS};

    if ( ref($data[0]) eq 'HASH' ) {
        # param($hash_ref)
        %{$self->{__PARAMS}} = (%{$self->{__PARAMS}}, %{$data[0]});
    }
    elsif ( scalar(@data) % 2 == 0 ) {
        # param(@array)
        %{$self->{__PARAMS}} = (%{$self->{__PARAMS}}, @data);
    }
    scalar(@data) == 1 ? $self->{__PARAMS}->{$data[0]} : $self->{__PARAMS};
}

C::A::P::Stash 的に param を使いたかった & lvalue 使ってみたかった

$obj->param->{'hoge'} = 'fuga'; # OK
$obj->param('hoge','fuga');     # OK
$obj->param('hoge') = 'fuga'    # OK
$obj->param({hoge => 'fuga'});  # OK
$obj->param(hoge => 'fuga');    # OK
$obj->param = {hoge => 'fuga'}  # OK

print $obj->param->{'hoge'};    # fuga
print $obj->param('hoge');      # fuga

フレームワーク (2)

HikiDoc を使った WEB アプリケーション」の時にはしりきれとんぼだったので、今回はちょっと続けてみようかと思う。今のところは

  • 名称は CGI::Minimal::App (仮)
  • ロジックは CGI::Application をほぼそのまま頂く
    • 使い方が変わると、自分自身が使いづらくなるので
    • 細かいあたりは、コーディングを楽しめるように自分流で
  • CGI::Minimal の perldocに「warnings と vars は重て!」とか書いてあるが、どうするかは作ってから考える
  • CGI::Application::Plugin で、いつも使っているものは最初からいれてしまう

フレームワーク

お昼過ぎ、ふと思い立ってフレームワークを作り始めたので、記録残し

CGI::Simple か CGI::Minimal を使って、機能を減らして、もうちっとシンプルな俺仕様 CGI::Application が欲しい。CGI::Application 使ってると、いろんなことを覚えることができないワシはコピペが増えて困る

イチから必要な機能だけ実装した方が楽かも。自分で実装したら覚えること減りそうだし

CGI::Simple よさげだけど、どうせなら CGI::Minimal 使った方が極端で楽しいかも。これで CGI::Application より重くなったら、自分の実装が悪いということで

CGI::Application のマネをするため、コード斜め読み

とりあえずここまで

トラックバックをどうすべきか

今に始まったことじゃないが、FreeStyleWiki からトラックバックしようとすると NG のことが多いので、そろそろ何とかすべきかどうか考え中

[ << < 6  7  8  9  10  11  12  13  14  15  16 >> ]

Home > Perl Archive

Feeds

Return to page top