わたしとVue 今すぐダウンロード

小粒なうぇっぶあぷりを作ってて、 Vue.js を使いたいなと思ってる(使ってる)

小さいしドキュメントも充実しているので、ちょっとガイド読めば使えるのであんまり把握せずに使ってるけど、それはよくないよねということでコード読むところから始めようと思う

読むのはこれ。

https://github.com/vuejs/vue

現時点の Latest release な 1.0.1 を読む

v-cloak

最初は v-cloak.

理由は特になくなんとなく、簡単にわかりそうだから

http://vuejs.org/api/#v-cloak

要素に付けておくと Vue オブジェクトのコンパイルが終わると消える属性で、コンパイルが完了する前にテンプレートが表示されてしまうのを防ぐために CSS と組み合わせて使ったりするやつ。

ファイルを見てみるとそのものずばりな src/directives/public/cloak.js というのがあるのでそこに目を通す。

予想通りわかりやすそう。

compiled というフックに 'v-cloak' という属性を削除する関数を登録しているように見える。

こっから少し掘り下げてみる。

bind という名前で関数を export しているのはきっとそういう決まりかな。

src/directives/public 以下の他の js を見てみても、 bind という関数を export していそうに見える

bind が使われているところとかはもう少し後で見る。

cloak で src 以下を検索してみると該当するのはわずか。

cloak.js 自体と src/directives/public/index.js で cloak.js を require しているところ。

それとあと一箇所 src/directives.js で 'cloak' が使われてる。

https://github.com/vuejs/vue/blob/1.0.1/src/directive.js#L68L75

場所は Directive というオブジェクトの _bind 関数

属性が 'v-cloak' でないか vmコンパイル済みだったら属性を消すという感じの処理。

descriptor.attr ってのはなんなのかわからないが、'v-' なんとかの属性はどっかのタイミングで消すもののようだ。

その時に 'v-cloak' を先に消さないようにするための分岐っぽい。

そうすると vm ってのはちゃんと見たほうがよさそうだな〜

Directive から辿ってくと、 vmコンストラクタの第2引数なので、 new してるところを見る。

src/intance/lifecycle.js で new してる。

https://github.com/vuejs/vue/blob/1.0.1/src/instance/lifecycle.js#L111

_bindDir の中で new していて、第2引数は this

ここでの thisexports してる module 自体って理解でいいのかな

ということはこの lifecycle のオブジェクトなのか・・?

確かに、 _compile という関数の中で this._isCompiled という変数を設定しているようだ。

https://github.com/vuejs/vue/blob/1.0.1/src/instance/lifecycle.js#L68

さっき読んだところで this.vm._isCompiled というのがあったからなんとなくあってそう。

https://github.com/vuejs/vue/blob/1.0.1/src/directive.js#L70

今読んだ範囲だと vm を使っているところはあとひとつ、 $once というのがあった。

しかし $once を export しているのは src/api/events.js だなぁ。

vue/directive.js at 1.0.1 · vuejs/vue · GitHub

これは一体どういうことか。 lifecycle を require しているところを見れば多分わかりそう。

https://github.com/vuejs/vue/blob/1.0.1/src/vue.js#L85L86

src/vue.js で require している。

なるほど、 p というオブジェクトに extend していってるんだね。

確かに require('./api/events') もしている。

ということは↑の vmp オブジェクトで、 $once も持っているんで理解正しそう。

$once は予想通りな感じで、一回だけ関数が実行されるように登録された関数を実行したら登録を削除する処理を挟み込むようなもの。

さてじゃあ compiled という hook を呼んでるのはどこかな?と考えると、さっき compile っぽい関数あったよね。

はい、lifecycle.js

で、_isCompiled の直後にあるね、 callHook('compiled')

https://github.com/vuejs/vue/blob/1.0.1/src/instance/lifecycle.js#L69

これだよこれ。

callHook は src/instance/events.js で定義されている

https://github.com/vuejs/vue/blob/1.0.1/src/instance/events.js#L155L163

handlers があればひたすら呼び出していて、 handlersthis.$options に hook ごとに登録されてる。

でもここまで handlers というのは特に出てこなかったような気がする。

$emit のほうが大事かな。

フックで実行する関数の登録処理は $once あたりでやってるはず。

$once を見ると、実際登録してるのは $on っぽい。

https://github.com/vuejs/vue/blob/1.0.1/src/api/events.js#L10L34

$onthis._events に関数を push してる。

$emit をみてみると

https://github.com/vuejs/vue/blob/1.0.1/src/api/events.js#L89L105

_event に登録されているコールバックを apply で呼び出してる。

ということで、ここで最初に読んだところで登録された 'v-cloak' 属性を削除するコールバックが呼ばれて、コンパイルが完了すると 'v-cloak' 属性が消えてくれるということだ。

多分。

とりあえずこんなところ。

なんとなく構造がわかってきたしその辺もまとめつつまた読む。

いつもこうなんとなく読み始めちゃうけど、最初に全体像を把握したりとか、あとコメントに色々書いてあるんでコメント読んだりとかちゃんとしたほうがいいな〜と反省する

macでターミナルの起動がめちゃくちゃ遅くなってた

最近家のmacのターミナルの起動が超遅くてストレスを感じてた

きっとzshrcにいろいろ書きまくっているからだろうとそろそろ治すか・・と思ってたら、どうもターミナルの起動時とかタブを新しく開いた時によく見てみると遅いのは login だった。

login が遅いで調べると asl を消すとか出てくる。

Speed Up a Slow Terminal by Clearing Log Files | OSXDaily

asl は Apple System Log ということらしい。

login 時に last login を表示するときにここを検索してるんでここが肥大化すると遅くなるとか。

システムログなんかいらない!(わけない)ということで早速 /var/log/asl 以下のログを消して再起動してみるけど改善せず。

他に方法はないものかと探してると俺しか使わないmacだし quiet に login すれば良さそう。

.hushlogin を置いておくとできるようだが touch ~/.hushlogin しても変化なし

原因わからないのでこの辺は時間あるときにもうちょっと調べたいがとりあえずは iTerm の Profiles から起動時のコマンドをデフォルトの Login Shell (login -fp ) から Command に変更して、Commandに login -qfp <user> と入れる

これで速くなったのでとりあえずしばらくこれでしのぐ

ハロー "Hello, World" がおもしろい

まだ3章までしか読んでないけど、『ハロー "Hello, World"』がおもしろい

最近はLinux Kernelのコード読んだりしてみたいな〜と思って読んだりしてたんだけど、やっぱ膨大なのでとっつきにくい。

そこでこんな本を見かけたものだから、"OSと標準ライブラリのシゴトとしくみ" ってのに惹かれて買ってみた。

はじめに、の部分を軽く読んで「手を動かして、調べかたを知る」とか、資料に頼るんじゃなくて手を動かして調べることを重視した本なんだということが書いてあっていいねーと思う

やっぱり自分で動かしながら動きを追ってみないと頭に入ってこないなーと思ってたので色々な角度から解析してる本とかとても魅力的。

というわけで読んでみると、僕のような素人にも優しい感じ。

一章でアセンブラな解説もあるしVMの使い方とかも載ってる。

親切親切

二章から GDB を使ってがんばって題名の Hello, World を解析していく。

GDB はあんまり使ったことがなかったけどまぁ本の通りにやっていけばなんとなく動かせる

disable とか知らなかったけど便利だ

ひたすら追いかけるのはどこでどうやって hello world って文字列が出力されるのかということ

それを知るためにステップ実行してアセンブリ読んでコード読んで、後は確かめるために文字列を出力している部分のバイナリをnopに書き換えてみて出力されなくなることを確認したり。

おもしろい!!

IO はカーネルがやるからシステムコールカーネルに処理を頼むんだよなーとかそのくらいはわかってたつもりだし、CPUは動くときにレジスタ使ってどうこう、スタック使ってどうこうとかもなんとなーく知ってたけど、hello worldでそれが具体的にどう動いてるかと言われるとまぁよーわからんなーという程度の知識しかなかったんで、それを丹念に追っていくのは大変興味深い

システムコールに引数をどう渡すか、どう値を返すのか、エラーをどうセットするのか。

負の値を返せないのどうしてるのかとか、標準ライブラリの役割とか。

知らんことばかりでした

動かしながら学ぶとなんとなく納得感があっていい。

先が楽しみ

システムコールの定義

itpro.nikkeibp.co.jp

を読んでgrepしたり、http://lxr.free-electrons.com/ident?i= で検索してもなかなかシステムコールを定義してる箇所が見つからないなーと思ってたら、

SYSCALL_DEFINEx っていうマクロを使うようになってたのね。

SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
    struct fd f = fdget_pos(fd);
    ssize_t ret = -EBADF;

    if (f.file) {
        loff_t pos = file_pos_read(f.file);
        ret = vfs_read(f.file, buf, count, &pos);
        if (ret >= 0)
            file_pos_write(f.file, pos);
        fdput_pos(f);
    }
    return ret;
}

とか。

SYSCALL_DEFINEx 自体は include/linux/syscalls.h で

#define SYSCALL_DEFINE0(sname)                   \
    SYSCALL_METADATA(_##sname, 0);              \
    asmlinkage long sys_##sname(void)
    
..(略)..

#define SYSCALL_DEFINEx(x, sname, ...)              \
    SYSCALL_METADATA(sname, x, __VA_ARGS__)         \
    __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)

#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
#define __SYSCALL_DEFINEx(x, name, ...)                 \
    asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))   \
        __attribute__((alias(__stringify(SyS##name))));     \
    static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__));  \
    asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));  \
    asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))   \
    {                               \
        long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));  \
        __MAP(x,__SC_TEST,__VA_ARGS__);             \
        __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));   \
        return ret;                     \
    }                               \
    static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))

とかで定義されてる。

rust で数値からenumに変換する

rustのenumを定数を列挙するためだけに使いたいということもありますね?(ないですか?)

そういう時、数値からenumに変換したいということがありますね?(ないですか?)

rustのenumはこんなふうに定義します。 rustのenumはだいぶ高機能なのでいろんなことができますが、今回は定数の列挙に使いたいという想定ですね。

enum TrafficLight{
    Blue,
    Yellow,
    Red,
}

このように定義するとデフォルトで0から数値がふられるので enum から数値に 変換することはできます。

fn main() {
    println!("{:?}  = {}", TrafficLight::Blue, TrafficLight::Blue as i32);
    println!("{:?}  = {}", TrafficLight::Yellow, TrafficLight::Yellow as i32);
    println!("{:?}  = {}", TrafficLight::Red, TrafficLight::Red as i32);
}

結果

$ cargo run
Blue    = 0
Yellow  = 1
Red     = 2

こうなります。

逆はできません。

$ cargo build
src/main.rs:12:32: 12:49 error: non-scalar cast: `i32` as `TrafficLight`
src/main.rs:12     let light : TrafficLight = 0 as TrafficLight;
                                              ^~~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `light`.

To learn more, run the command again with --verbose.

こうなります。

調べてみると以下がでてきますね。

stackoverflow.com

書いてある通りに std::num::FromPrimitive は削除されてしまいましたが、今は http://doc.rust-lang.org/num/num/index.html に同様な機能を持つものが入っています。

crateに頼ることになるのは遺憾ですが公式が提供してる(?)ものなのでまぁいいとしましょう。

これを使って FromPrimitive という trait を実装すると

from_i64(n: i64)
from_u64(n: u64)
from_isize(n: isize)
from_i8(n: i8)
from_i16(n: i16)
from_i32(n: i32)
from_usize(n: usize)
from_u8(n: u8)
from_u16(n: u16)
from_u32(n: u32)
from_f32(n: f32)
from_f64(n: f64)

これらが使えるようになるので、基本の数値型ならどれからでも変換できるようになります。

実装する必要があるのは、 from_i64from_u64 の2つです。

以下使い方

Cargo.toml に依存を追加しましょう

[dependencies]
num = "*"

で実装してきます

extern crate num;
use num::traits::FromPrimitive;

impl FromPrimitive for TrafficLight {
    fn from_i64(n: i64) -> Option<TrafficLight> {
        match n {
            0 => Some(TrafficLight::Blue),
            1 => Some(TrafficLight::Yellow),
            2 => Some(TrafficLight::Red),
            _ => None,
        }
    }
    fn from_u64(n: u64) -> Option<TrafficLight> {
        match n {
            0 => Some(TrafficLight::Blue),
            1 => Some(TrafficLight::Yellow),
            2 => Some(TrafficLight::Red),
            _ => None,
        }
    }
}

こうです。

このmatchあたりがめんどくさいのでなんとかしたいですね。いい方法があるといいんですが。

ここに数値を書かないといけないとなると網羅してるかもよくわからないし変更や追加に弱いしこれはなんとかしたいです。

(これのいい方法が知りたくてこんな記事をだらだら書いてると言っても過言ではありません。誰か教えてください。)

    let blue = TrafficLight::from_i64(0 as i64).unwrap();
    let yellow = TrafficLight::from_u8(1 as u8).unwrap();
    let red = TrafficLight::from_usize(2 as usize).unwrap();
    println!("{:?}", blue);
    println!("{:?}", yellow);
    println!("{:?}", red);

結果

$ cargo run
Blue
Yellow
Red

できましたね

mixlib-cliのオプションで複数の値を渡す

github.com

mixlib-cli、便利ですよね。

この option で同じオプションで複数の値を渡したい時はどうすればいいか

例えば --hosts複数のホストの情報を渡したいとか。

ぱっと調べた感じ&動作を見た感じでは、 cmd --hosts host1 --hosts host2 とかいう渡し方でうまく処理してくれるということはなさそう

:proc オプションを使うとそれっぽくできる

:proc オプションは、 Proc を渡しておくと渡された値をその関数で前処理しておいてくれる。

options :hosts,
             :long => "--hosts",
             :proc => Proc.new { |a| a.split(",") }

↑のようにしておくと cmd --hosts host1,host2複数の値をカンマ区切りで渡せば、プログラム内で config[:hosts] = ["host1", "host2"] として使える。

テーブルのカラムにないデータをEloquentのレスポンスに入れる

なんて言ったらいいかよくわからないけどタイトルみたいなことがしたいときどうするか

テーブルのデータそのものじゃなくてテーブルのデータから計算できるデータがあったとして、それをクライアントに計算させるんじゃなくてレスポンスに入れて返したいとかそんな時

普通にドキュメントに書いてあるけど、そういう時は Accessors と $appends ってのを使うとできる

Accessors は↓これ。で、 appends については同じページの一番下に書いてある

Eloquent ORM - Laravel - The PHP Framework For Web Artisans

$appendsEloquent を継承してるクラスのメンバ変数として定義しておく

class SomeModel extends Eloquent
{
    protected $table = 'some_table';
    protected $appends = array('some_append_data'); // ←これ

    // Accessors    
    public getSomeAppendDataAttribute()
    {
        return "something";
    }
}

こうすると、 SomeModel::find($id) とかで返ってくるデータに

    "some_append_data" =>  "something"

も一緒に入ってくる。