Quiver Export #ruby #markdown
Quiverのノートブックをテキストファイルにエクスポートするツールを作りました。
nori3tsu/unofficial-quiver-export
Quiverの内部で保存しているjsonをパースしてテキストファイルにエクスポートするだけのツールです。Cronで定期的にクラウドストレージにエクスポートすることで、Quiverのノートの中をどの端末でも見ることが出来るようになります。
Text CellはHTMLになっているため、エクスポートしたテキストファイルの中にHTMLが含まれます。
インストール
gem install unofficial-quiver-export
使い方
quiver-export --in $HOME/Dropbox/Apps/Quiver/Quiver.qvlibrary --out $HOME/Dropbox/Apps/Quiver/Quiver.export
定期実行
crontab -e
を使います。
LC_CTYPE=en_US.UTF-8 */5 * * * * $HOME/.rbenv/shims/quiver-export --in $HOME/Dropbox/Apps/Quiver/Quiver.qvlibrary --out $HOME/Dropbox/Apps/Quiver/Quiver.export > $HOME/.quiver-export/quiver-export.log 2>&1
-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
SSHログインでタイトルのエラーが発生するようになったときの解決方法。
Terminal
以下の設定のチェックを外す。
Preferences > Profiles > # Advanced # Set locale environment variables on startup
iTerm2
以下の設定のチェックを外す。
Preferences > Profiles > Terminal # Environment # Set locale variables automatically
参考
Quiver: MacのMarkdown Editor #mac
MacのMarkdown EditorをQuiverに乗り換えたので紹介したいと思います。
Markdownいいですよね。簡単なメモから技術的なメモまでシンプルに書けるのでとっても気に入っています。 Macで使えるMarkdown EditorとしてKobitoの操作感が好きでずっと使っていました。Kobito最高なのですが、旧バージョンのKobitoは複数端末の同期が出来ないことと、.mdファイルへの書き出しがそれほど使い勝手が良くないことから、以下の条件で移行先をずっと探していました。
様々なアプリを試しては挫折してを繰り返していたのですが、ようやく満足できるアプリを発見しました。 'プログラマーのためのノートブック'として作られている'Quiver'というアプリです。 これは非常に多機能かつ軽く、ほぼ全ての条件を満たしてくれて大変満足しています。
Mac App Store - Quiver: The Programmer's Notebook
不満点は以下の2点ですが、1は現在Issueがあがっていて対応中とのこと。2は現状どうしようも無いですが、Notebook単位で.mdファイルに書き出しできるのでそれで代替できないこともないです。
No Syntax highlighting for code block of a Markdown cell type · Issue #70 · HappenApps/Quiver
トライアル版もあるので、同じような悩みを抱えている方は試してみてはいかがでしょうか。
2015-04-29 追記: Quiverの中身をエクスポートするツールを作りました。
Quiver Export #ruby #markdown - nori3tsu's blog
設定
参考までに私の設定の変更点を共有します。
General
- Apperance: Dark
- Default Cell Type: Markdown Cell
Cells
Code Cell
- Key Binding: Vim
Markdown Cell
- Key Binding: Vim
Styles
Preview/PresentationモードのCSSに参考リンクのgithub-markdown.css
を追加する。QuiverのCSSスタイルに合わせるため、CSS内部の.markdown-body
を.markdown-cell
に置換する。
Sync
- Dropbox同期
Web APIを作る上で考えていること
ここ数年、Web API(以降API)を作る機会が増えています。例えば、スマホやシングルページアプリケーションのバックエンド,システム間のデータ連携などです。 これらのAPIを複数の言語やフレームワークで実装してみましたが、個々の機能を実装する前に考えるべき事は共通していました。これから先も多くのAPIを作成する事になると思いますので、APIを作る上での共通実装をまとめてみたいと思います。
目次
- 文字コード
- 日付書式
- リクエストフォーマット
- レスポンスフォーマット
- API認証
- Validation
- トランザクション
- ログ出力
- 横断処理
- 共通例外処理
- 設定ファイル
- 処理時間の計測
- X-Request-ID
- ヘルスチェック
- 単体テスト
- デプロイ
検討項目
文字コード
UTF-8を選択します。
日付書式
ISO8601形式を選択します。 曖昧さを無くすためタイムゾーン情報を付与したいためです。
例: 2015-04-07T09:00:00+0900
リクエストフォーマット
POST・PUTのリクエストボディはJSONを選択します。
レスポンスフォーマット
JSONを選択します。
API認証
APIの認証方法とリソースの権限制御の仕組みを考えます。 それぞれ一長一短がありますので、要件によって適切な方法を選択します。
...
Validation
入力されたパラメータを簡単に検証するための仕組みを考えます。 RailsだとActiveRecordの標準機能、JavaだとHibernateValidatorなど、メタ情報から検証出来るものを選択します。 また、検証に失敗した項目を構造化したレスポンスで返せる用に拡張します。
トランザクション
業務ロジックの正常終了・異常終了を判断して自動的にコミット・ロールバックする仕組みを考えます。 これを導入しておくと、トランザクションの張り忘れやロールバック忘れなどの些細な不具合が少なくなります。
ログ出力
ログ出力先:
- ファイル
- データベース
- Fluentd
ローテーション周期:
- 日次
- 週次
- サイズ
ローテーション手段:
- Loggerの機能
- OSのlogrotate
出力フォーマット:
共通のログ出力:
- リクエスト・レスポンスのDEBUGログ
- SQLのDEBUGログ
...
横断処理
業務ロジックの前後に処理を入れる仕組みを考えます。 別項にあるトランザクション・共通例外処理・処理時間計測・X-Request-IDの付与などで使います。
...
共通例外処理
アプリケーションの業務ロジックで発生した例外を適切に処理するポイントを考えます。 APIの場合、例外によってレスポンスを選択することが多いです。
- 不正なリクエスト・Validationエラー: 400 Bad Request
- 認証失敗: 401 Not Authorized
- リソースに対する権限なし: 403 Forbidden
- リソースが存在しない: 404 Not Found
- リソースの競合: 409 Conflict
- サポートされていないメディア・タイプ: 415 Unsupported Media Type
- その他の例外: 500 Internal Server Error
...
設定ファイル
開発・ステージング・本番環境など、各種環境で設定ファイルを切り替える方法を考えます。
処理時間計測
パフォーマンスを測定するために、リクエスト毎に処理時間を計測します。
X-Request-IDのログ埋め込み
障害発生時や関連システムからの問い合わせなどで対象のリクエストを一意に識別するために、レスポンスにX-Request-IDとしてUUIDを付与します。
ヘルスチェック用URLの用意
ロードバランサーなどから監視するヘルスチェック用のURLを用意します。 DBなど、APIの提供に必要なミドルウェアへの疎通に成功したら正常ステータス(200)を返す処理にします。
余談ですが、外部からの設定でヘルスチェック用URLのレスポンスを200 or 503と切り替える機能を付けると、アプリの設定でロードバランサーから切り離すことが出来るようになるため便利です。
単体テスト
選択するフレームワークや組み合わせるライブラリによって、特定のオブジェクトを生成することが難しいなどの理由で、単体テストの実装が難しくなってしまうことがあります。また、初期の段階で導入しておかないと、テストを意識した設計ができずにテストし辛いクラスが出来あがってしまうことがあります。 私の場合、忙しさに追われて単体テストを書かないという状態に陥ってしまったことがあり、その際にソフトウェアの品質が著しく下がってしまった経験から、単体テストを実行する仕組みを最初に整備しておくことにしています。 また、この段階からJenkinsなどのCIサーバと連携するために、CUIから実行できるようにします。
- Controllerのテスト
- Modelのテスト
- Viewのテスト
- Mock/Stub
- 生成が困難なオブジェクト
- DIコンテナ
- HTTP通信
...
デプロイ
稼働するサーバに向けてのデプロイ方法を考えます。 後々JenkinsなどのCIサーバと連携できるようにCUIから実行できるようにします。
おわりに
最近、これらの事をRailsで実装する機会があったのですが、驚くほど簡単に実装できてしまいました。 Javaで複数のライブラリや設定ファイルを組み合わせて実装していた頃にはもう戻れませんね。
Java+RSA公開鍵暗号化 -> Ruby+RSA秘密鍵復号
JavaからRSA公開鍵で暗号化したデータをRubyからRSA秘密鍵で復号するサンプル。
鍵の保存
require 'openssl' OpenSSL::Random.seed(File.read("/dev/random", 16)) rsa = OpenSSL::PKey::RSA.generate(2048) # 秘密鍵を保存 File.open("private_key.pem", "w") do |f| f.write(rsa.export) end # 公開鍵を保存 public_key = rsa.public_key File.open("public_key.pem", "w") do |f| f.write(public_key.export) end
Java+RSA公開鍵暗号化
package com.example; import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; public class RSAPublicKeyExample { public static void main(String[] args) throws Exception { RSAPublicKeyExample example = new RSAPublicKeyExample(); String encrypted = example.encrypt("test"); System.out.println(encrypted); } public String encrypt(String data) throws IOException, GeneralSecurityException { // ファイルから公開鍵を読み込む PublicKey key = readPublicKeyPem(this.getClass().getResourceAsStream("/public.pem")); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); // 暗号化+Base64 byte[] encrypted = cipher.doFinal(data.getBytes()); return Base64.encodeBase64String(encrypted); } private PublicKey readPublicKeyPem(InputStream stream) throws IOException, GeneralSecurityException { // PEMのヘッダとフッタを削除 String pem = IOUtils.toString(stream) .replaceAll("(-+BEGIN PUBLIC KEY-+\\r?\\n|-+END PUBLIC KEY-+\\r?\\n?)", ""); byte[] decoded = Base64.decodeBase64(pem); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoded); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey key = keyFactory.generatePublic(keySpec); return key; } }
Ruby+RSA秘密鍵復号
require 'openssl' require 'base64' # ファイルから秘密鍵を読み込む rsa = OpenSSL::PKey::RSA.new(open('private_key.pem')) # 復号 puts rsa.private_decrypt(Base64.decode64('{Javaで暗号化+Base64した文字列}')) # => test
参考
VarnishのコンパイルでError 1
エラーメモ
環境
- CentOS 6.5
- Varnish 3.0.6
現象
Varnishをコンパイル中に以下のエラーが発生。
varnishadm.c: In function ‘interactive’: varnishadm.c:234: error: ‘rl_already_prompted’ undeclared (first use in this function) varnishadm.c:234: error: (Each undeclared identifier is reported only once varnishadm.c:234: error: for each function it appears in.) varnishadm.c:236: error: ‘rl_attempted_completion_function’ undeclared (first use in this function) varnishadm.c:297: warning: implicit declaration of function ‘rl_forced_update_display’ varnishadm.c:300: warning: implicit declaration of function ‘rl_callback_read_char’ make[3]: *** [varnishadm-varnishadm.o] Error 1 make[3]: Leaving directory `/home/vagrant/download/varnish-3.0.6/bin/varnishadm' make[2]: *** [all-recursive] Error 1 make[2]: Leaving directory `/home/vagrant/download/varnish-3.0.6/bin' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/home/vagrant/download/varnish-3.0.6' make: *** [all] Error 2
原因
readline-develがない。
対策
$ yum install readline-devel