解せぬ日記

雑な話をする

Arch LinuxでActivitiesを使うとカーソルが消える話

TL;DR

Gnome3を使ってて、Activitiesをクリックしたら波アニメーションの後にマウスカーソルが消えてしまうという人へのワークアラウンドは以下。

$ yaourt -U /var/cache/pacman/pkg/mutter-3.18.2-1-x86_64.pkg.tar.xz

Arch Linux kawaii.

背景

いつの頃からか忘れたけど、Activities Hot Cornerを使うときにマウスカーソルが消えてしまって、異常に不便になった。 Activities Hot Corner(アクティビティ)という呼び方が正しいのかもわからないけど、ArchWikiにはそう書いてあったからそう呼ぶことにする。

以下のサイトの最上部にある画像のようなメニューとワークスペースとウィンドウが俯瞰できる状態のときに消えてしまうので、Tabとかで選択してた。

www.gnome.org

解決法

色々調べた感じだとmutterが悪いんじゃないかという当たりをつけたので、キャッシュからダウングレードを実行する。 ちなみにmutterは何かというとGNOME用のウィンドウマネージャとのこと。

$ yaourt -U /var/cache/pacman/pkg/mutter-3.18.2-1-x86_64.pkg.tar.xz

ただこれはワークアラウンドでしかないので、ちゃんとアップデートを確認しつつ、アップデートが出たら上げていくのがよいと思う。

Bugsにちゃんと報告上がってた。

bugs.archlinux.org

Alamofireで204 No ContentなAPIのレスポンスをどう扱うか

https://media.giphy.com/media/aWjpyBmKXQRAA/giphy.gif

TL;DR

現状、SwiftのHTTPクライアントであるAlamofireで204 No ContentなAPIの処理のベストプラクティスは存在しないので、responseで受けるか、Response Serializerを作るか、自分でResponseを作って泥臭くやるしかない。 Response Serializerを作るのが、他のAPIの処理と同じように実装できていいように僕は思う。

背景

Swift 2.0とiOS 9対応をしていて、Alamofireのバージョンが上がったことで、AlamofireがResponse(Struct)とResult(Enum)を持つようになった。

それに伴い、responseJSONresponseStringなどはデータが返ってくることを期待した実装に変更され、通信完了時のハンドラにResultを含むResponseが渡されるようになった。 (以前、使っていたバージョンではそういったものはなく、Request, Response, Data, ErrorがOptionalで渡される実装だったので、自前でResponseを定義して扱っていた。)

// 以前: ハンドラにrequest, response, json, errorのOptionalが渡されている
Alamofire.request(urlRequest)
    .validate(statusCode: 200..<300)
    .responseJSON { (request, response, json, error) in
        // code     
     }

// 現在: ハンドラにResponse<AnyObject, NSError>が渡される
Alamofire.request(urlRequest)
    .validate(statusCode: 200..<300)
    .responseJSON { response in
        // code     
     }

response以外の実装ではデータが返ってくることを期待しているので、204 No Contentの場合にシリアライズエラーとなって処理が失敗したことになってしまう。

対策

対策は幾つか思いつく。

  • responseresponseJSONresponseStringから呼び出されるメソッドで、通信完了時に呼び出されるハンドラにRequest, Response, Data, ErrorがOptionalで返ってくるので、他のAPIとは別の方法でデータを処理する
  • responseとAlamofireのResponse、Resultを組み合わせて、他のAPIと同じ処理ができるようにする

けど上記の方法はいずれもアドホックな対応になり、微妙な気がしてやめた。

Issueを巡っていると、コミッタの人が例えばNo Dataを扱うResponse Serializerなんかあったらどうかみたいな話をしていて、Response Serializer作れることが分かった。 Response Serializerを作るとresponseJSONと同じようにレスポンスを扱えるので便利そうだし、作るぞ!!という気持ちになったので作った。

github.com

実装

ドキュメントにXMLのResponse Serializerのサンプルがあったので、これを参考にした。

https://github.com/Alamofire/Alamofire#creating-a-custom-response-serializer

extension Request {
    public static func NoContentResponseSerializer() -> ResponseSerializer<AnyObject, NSError> {
        return ResponseSerializer { request, response, data, error in
            guard error == nil else { return .Failure(error!) }

            guard let _ = data else {
                let failureReason = "Data should not exist. Input data should nil."
                let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
                return .Failure(error)
            }

            return .Success("")
        }
    }

    public func responseNoContent(completionHandler: Response<AnyObject, NSError> -> Void) -> Self {
        return response(responseSerializer: Request.NoContentResponseSerializer(), completionHandler: completionHandler)
    }
}

.Success("")で空文字を返してるのはちょっとした理由があって、responseJSONResponse<AnyObject, NSError>を返してくるので、そこを揃えたかったため。

本来であればnilを入れて返したいところで、もうちょっとうまい実装があればOptionalとして返したりできそうだが、OptionalとAnyObjectを同じように扱うにはAnyを使う必要があって、現時点ではSwfit 2.0とiOS 9対応を優先させて、とりあえずこれで動くようにしてる。

あとは呼び出し側で、

Alamofire.request(urlRequest)
    .validate(statusCode: [204])
    .responseNoContent { response in
        // code
    }

のように呼び出せば良い。

まとめ

他にいい方法があったり、こんなやり方イケてないだろって話があれば、ぜひ教えていただきたく、何卒。 AnyObjectは割とよく使うけど、Anyって結構使うもんなんだろうか…。

作れないかもしれないけど作った話 at MF Geeks Night

f:id:terut:20150731111429j:plain

TL;DR

最近Swiftに入門してて、作れないかもしれないけど勢いでライブラリを作った。 練習も兼ねて自分に必要なライブラリを作ると他のライブラリの作りを調べたりとかSwiftっぽい書き方とか目にできるので、学びがあってよい。 国家権力が白紙に戻すこともないので、作れないかもしれなくても勢いで作るぞ!!

github.com

LT at MF Geeks Night

speakerdeck.com

先月に引き続き、@ppworks さんに声をかけてもらってMF Geeks Nightに行ってきた。 MF Geeks Nightについては MF Geeks Nightに行ってきた - 解せぬ日記 を見てもらうとよい。

LT募集です!と言われながらも、珍しく仕事が忙しいのとチキンなのがあって資料ができるか分からなかったのでLTに関しては返事をしてなかったんだけど、開始1時間前ぐらいにウオオオオオオオオオオオオオとなって資料を作り始めたら、雑すぎる資料ができたんで、枠空いてたらやることに決めた。

枠空いてたらやることに決めたはずなんだけど、気がついたらLTしてた。

まとめ

  • 新しい言語をやるときにライブラリを作ると色々学びがあってよい。
  • 作れないかもしれないけど作るぞ!!ぐらいの勢いが大事。

競技場に触れたかっただけかな?

MF Geeks Nightに行ってきた

f:id:terut:20150626001820j:plain

TL;DR

プロダクトを作る上での文化が醸成されつつある雰囲気を感じつつも、自分で色々やっていけそうな余地もあり、楽しそうな職場だったんでオススメだと思う。興味ある人はぜひマネーフォワードに遊びに行ってみるとよさそう。

事の始まり

@ppworksさんがエスパーになった結果、MF Geeks Nightというのがあるからどう?みたいな話をもらった。以前から開催されていたようで、ブログにも様子が上がってる。

moneyforward.com

毎回ゲストを呼んで開催しているとのことで、他の会社の勉強会に参加するのは結構新鮮だった。

やったこと

毎回、面白くなるように色々考えられているようで、今回は社内の各チームの開発環境や開発フロー、取り組んでいることについて発表するスタイルだった。すごく色んな取り組みを自発的にやっているようで、各チームがよりよい開発を目指してたのが印象的だった。

一応外部の人間に言ってた内容なので、公開してもよい情報だろうけど、ハッシュタグなどはなかったんで、内容については触れない。

まとめ

とにかくマネーフォワード各位に勢いがあって、最終的に入社だぁ〜みたいな奇声を発するようになっていた。奇行種かな?

何が起こったのか分からなかったけど、とにかく勢いがある(大事なことなので2回ry)上に技術の話もできて最高〜。

僕はぼっち力がだいぶ高いので、ぼっちになるかな〜と思ってたんだけどppさんに色々配慮していただいて、エンジニアの方を紹介してもらったりして楽しく過ごせた。感謝しかない!

systemd-tty-ask-password-agentの使い方

TL;DR

Please enter password with the systemd-tty-ask-password-agent tool!と言われたら、別のパネルなりウィンドウなり開いて、systemd-tty-ask-password-agent --queryを実行すれば良い。

systemd-tty-ask-password-agentの使い方

Arch LinuxはSystemdを採用してて、Systemdを使ってOpenVPNとかでVPN接続するときに以下のようなメッセージが表示されることがある。

$ systemctl start openvpn@client

Password entry required for 'Enter Private Key Password:' (PID 6145).
Please enter password with the systemd-tty-ask-password-agent tool!

メッセージにはsystemd-tty-ask-password-agentを使ってパスワードを入れてねと書いてあるわけだけど、ノリでそのままパスワード入力するとパスワードがまんま表示され、タイムアウトの後に次のインプットとして入力され、実行される。

どうやってパスワードを入力すんだぜ?と思ってたら見つけた。

issue with Vpn HideMyAss / Newbie Corner / Arch Linux Forums

別のターミナル開いて実行するといいよとのこと。

$ sudo systemd-tty-ask-password-agent --query
[sudo] password for terut: 
Enter Private Key Password: ****************

入力するとこんな感じでパスフレーズが聞かれて、接続が確立した。

ちなみにもっとよいやり方がないかとドキュメントを見てみたけど、systemd-tty-ask-password-agentはこういった使い方をするものっぽい。

Ubuntu Manpage: systemd-tty-ask-password-agent - List or process pending systemd

プロセスを見ていると/usr/bin/systemd-tty-ask-password-agent --wallというのがあったんで、こいつがフォワードしてメッセージを出してるってことなのかな。

あとOpenVPNには--askpass [file]ってコマンドライン引数があってファイルにパスワードを書いてもよさそうだったけど、嫌だったので却下した。

ちなみにOpenVPNのSystemdのUnitはリスト表示するとopenvpn@.serviceってなってるんだけど、これはUnitファイルの中で引数を受け取るためで、起動はリストで表示されたものではなく、@のあとに引数を与えて起動することになる。

# systemctl start openvpn@[設定ファイル名]のような感じで、もしclient.confを読むなら
$ systemctl start openvpn@client

コマンドラインからVPN接続最高〜。

Arch LinuxでSkypeがクラッシュする

Skypeがクラッシュして全く開けなくなった。一瞬ウィンドウが開いて、すぐ閉じる感じ。

すでにバグ報告は上がっていた。

FS#45204 : [lib32-qt4] [skype] Skype immediately crashes after launch

lib32-qt4をlib32-qt4-4.8.7-1からlib32-qt4-4.8.6-4へダウングレードすればいいらしい。

$ sudo pacman -U /var/cache/pacman/pkg/lib32-qt4-4.8.6-4-x86_64.pkg.tar.xz

Arch Linuxかわいい。

追記 2015/06/06 23:00

lib32-qt4-4.8.7-2がマッハで来たので、直った。

KeePassXのデータベースがコンフリクトした話

僕はパスワード管理にKeePassXを使ってる。

そのデータベースファイルがコンフリクトするという地獄みたいなことが起きた。

f:id:terut:20150605104240p:plain

経緯

Dropbox*.kdbファイルを同期して、Win/Mac/Linuxで参照できるようにしてるんだけど、Arch LinuxDropboxがいつからか常駐しなくなってて、それを直したタイミングで*.kdbファイルがコンフリクトしてしまった。

Dropboxのファイルはコンフリクトすると、競合コピー(confliected copy)とかってファイルを新たに作るので、自分でマージする必要がある。

*.kdbのコンフリクトは色んな理由でやっかいで、だいぶ辛かった。

KeePassには同期機能があるっぽくて、KeePass使えば解決じゃんみたいな話かも知れないんだけど、家のメインマシンがLinuxだったこともあって、KeePass 2.0が使えなかったか何かでKeePassXを採用してた経緯がある。

KeePassってMacOSXとWinでデータベースファイルの拡張子が違ったりしてたような記憶があるんだけど、今どうなってるんだろ?そもそも僕の勘違いで違わないのかな??

競合した内容を調査

当然、マージするには競合した内容を知る必要がある。

*.kdbはマスターパスワードをつかって暗号化されてるので、そのままで差分を知ることはできない。

どうやって差分を知るかというと、エクスポート機能を使ってテキストファイルかXMLファイルに吐き出すか、GUI上から超神技「目grep」を使うしかない。

僕みたいな一般人はエクスポート機能を使ってdiffを叩くなりするのがよさそうなんだけど、問題としてアホみたいに差分が出る。

実際見てみたけど、はっきり言って絶望しかない。

絶望した結果

golangを勉強してたので、XMLをパースして同じアイテムの差分を見て教えてくれるコマンドラインツールを書いた。

golangで書いておくと、WinでもMacOSXでもLinuxでも簡単に使えるやんけと思ったので、ちょうどよかった。

とりあえずどのアイテムがコンフリクトしてるのかが分かれば幸せになれそうだったので、その程度の作り込みしかしてない。

https://raw.githubusercontent.com/terut/kdb-diff/master/screenshot/screenshot1.png

こんな感じでマスターにあるやつとコンフリクトしたやつのアイテム名が出る。

github.com

まとめ

だいぶニッチだけど、golang書く練習になってよかった。

コンフリクト解消して幸せになろうな。