tag:blogger.com,1999:blog-285408582024-02-18T22:20:55.978-08:00open technicatechnical notes about web, languages, graphics or other software development stuff.daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.comBlogger62125tag:blogger.com,1999:blog-28540858.post-1962121737326671372017-12-29T04:51:00.000-08:002017-12-29T04:51:53.216-08:00コードレビューについての覚書最近、多少まとまった時間を使ってコードレビューをする機会があったので、僕の考えるコードレビューのポイントを備忘としてまとめておく。<br />
<br />
ただし、以下は前提。<br />
* Github、あるいはそれに類似したレビューシステムを利用している。SCMはGit。<br />
* 商用というか、仕事のコードレビューである。<br />
<br />
<hr />
<br />
<h3>
プルリクの目的が明確であり、レビュワーがそれを理解できるようになっている</h3>
<br />
そのプルリクが何をしようとしているのか、レビュワーはレビュー前に理解していないといけない。だからプルリクの最初のコメントでそれがきちんと説明されているかを確認する。目的がわかればレビューにどれだけ力をかければ良いかもわかる。例えば一回だけしか使わない運用スクリプトなら、細かいフォーマットの崩れとかを逐一指摘する必要はないが、実行内容の正しさは十分注意してみないといけない。<br />
<br />
差分を見ればそのプルリクで何をやっているかわかる、という主張ももしかしたらあるかもしれないが、それはちょっとやろうとしていることが逆転している。目的に対してコードの修正が正しいことを確認しなければいけないのに、書かれたことからやろうとしていることを忖度しようとしたら、本来の目的でないものをOKとしてしまうかもしれない。<br />
<br />
<br />
<h3>
Githubのプルリク画面だけではなく、checkoutして全体のコードを見て、修正漏れがないことを確認する</h3>
<br />
当たり前といえば当たり前だが、ある程度の修正をちゃんとレビューするならプルリクの画面だけでは仕切れない。一旦ローカルにチェックアウトして全体をレビューする必要がある。変更する必要があるのに漏れているケースなどは差分には出てこない。修正漏れがないことを確認する必要がある。チェックアウトした上でのgrepはとても効果がある。うまくキーワードを見つけてgrepする。特にコードを削除する修正の時など、削除もれがないように注意する。削除すべきタイミングでしないと、消して良いかわからないコードが残り、これを消すのに勇気が必要になってしまう。(本来自動テストで担保するべきではあるけど)<br />
<br />
<br />
<br />
<h3>
プルリクの目的に対して、変更点が適切である</h3>
<br />
機能を追加しようという時に、追加するべきファイルが適切かを見ることで、大枠の設計として問題ないかを確認する。git diffの--name-onlyオプションが便利。ちなみに最近覚えたけど、リモートネームを指定すればローカルにマージ先をチェックアウトする必要はない。例えばmasterにfeature_Aブランチからプルリクが出ている場合は、以下のコマンドで修正ファイルを確認する。<br />
<br />
<pre class="prettyprint">$ git checkout feature_A
$ git diff origin/master —name-only
</pre>
<br />
<br />
<h3>
プルリクの目的外の問題を見つけたら、(別の問題であっても)指摘する</h3>
<br />
これは異論があるかもしれない。本来プルリクの目的以外の修正は、別のプルリクで対応するべきではある。<br />
とはいえ、実務でレビューしていて何か問題を見つけた時、その流れで指摘した方が作業効率がいいのは確か。また、プルリクの目的から本当に大きくそれた問題を見つけることはあまりない(そもそもそういう箇所は見ない)。あえて別の修正を依頼するために担当者にプルリク以外の手段で修正を依頼して、そっちで別のプルリクを作ってもらう手間と、その作業の間にうっかり忘れてしまったりするリスクを考えると、見つけたその場で指摘する方が漏れがなくて良いと思っている。<br />
<br />
<br />
<h3>
名前については(クラス、メソッド、変数等)、適切でないものは細かくても指摘する</h3>
<br />
あえて書かなくても当然だが、コードにおいて名前は本当に重要。もちろんここにはコメントの適切さなども含まれる。可読性が低下するとその後のメンテナンス性が低下するのはもちろん、レビューの効率も悪くなる。<br />
あとスペルミスは絶対に修正する。スペルミスがあるとgrepで見逃したりする可能性がある。<br />
<div>
<br /></div>
daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-33137330189189915882014-03-27T00:36:00.001-07:002014-03-27T00:36:20.165-07:00mavenで依存ライブラリ一覧をHTML形式で出力する次のコマンドで、プロジェクトが依存しているライブラリの一覧のHTMLファイルを出力できる。このとき、ライブラリがさらに依存しているライブラリも再帰的に集めてくれる。
<pre class="prettyprint">
$ mvn project-info-reports:dependencies
</pre>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-34409573862516886332014-03-26T21:46:00.000-07:002014-03-26T21:46:02.608-07:00IEでの互換表示をX-UA-Compatibleの設定で切り替える<p>
作ったWebサイトをIEで表示確認すると、自動で古いバージョンの互換表示されてしまうことがある。
これは開発者ツールのエミュレーションタブにあるドキュメントモードで確認できる。
<p>
たとえばこれを常に最新のモードで表示したい場合、以下のようなmetaタグをheadに追加する。
<pre class="prettyprint">
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
</pre>
<p>
contentにはこれ以外にも任意のエミュレーションモードを指定するために"IE=7; IE=8"のように設定することもできる。daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-25169777665769307842013-12-11T22:00:00.000-08:002013-12-12T07:04:29.696-08:00Spring MVCでThymeleafを使う<h3>Thymeleafについて</h3>
<p>
<a href="http://www.thymeleaf.org/">Thymeleaf</a>はJSPに変わるような、主にHTML向けのテンプレートエンジン。JSPよりも高性能らしい。大きな特徴は、HTMLとしても妥当なマークアップでテンプレートを記述できること。同様のアプローチはSeasarファミリーに<a href="http://mayaa.seasar.org/index.html">Mayaa</a>というのがあった。Mayaaはテンプレートのほかに、データとテンプレートのマッピング用のXMLを用意する必要があったのがイマイチだった。Thymeleafは普通にテンプレートファイルは一つで大丈夫。
</p>
<p>
ここではSTSのSpring MVCのテンプレートで作成したプロジェクトのテンプレートエンジンを、Thymeleafに変更する。
</p>
<h3>Mavenで依存を解決</h3>
<p>
pom.xmlのdependencyに以下を追加。
<pre class="prettyprint">
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring3</artifactId>
<version>2.0.16</version>
</dependency>
</pre>
で、以下の(あるいは他の)コマンドを実行。
<pre class="prettyprint">
$ mvn install
</pre>
</p>
<h3>Springの設定</h3>
<p>
Springの設定ファイルでテンプレートエンジンをJSPからThymeleafに変更。
<pre class="prettyprint">
<!--
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
-->
<beans:bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".html" />
<beans:property name="characterEncoding" value="UTF-8" />
<beans:property name="templateMode" value="HTML5" />
<beans:property name="cacheable" value="false"/>
</beans:bean>
<beans:bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<beans:property name="templateResolver" ref="templateResolver" />
</beans:bean>
<beans:bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
<beans:property name="characterEncoding" value="UTF-8" />
<beans:property name="templateEngine" ref="templateEngine" />
</beans:bean>
</pre>
</p>
<p>
注意点としては、開発用にテンプレートのキャッシュを無効にしてある(デフォルトでは有効)。プロダクションにでプロイするときにはこの設定を有効にするべきでしょう。<beans:property name="cacheable" value="false"/>という箇所。
</p>
<h3>テンプレートを記述</h3>
<p>
あとはWEB-INF/views以下にテンプレートをThymeleafの書式で書いていくだけ。Spring MVCのコントローラからの呼び出し方法についてはJSPと全く同様。
ただし、テンプレートのHTMLには以下のような宣言が必要。Thymeleaf単体で利用するのとは違い、thymeleafに'-spring3'というサフィックスがつくのに注意。
<pre class="prettyprint">
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring3-3.dtd">
<p th:utext="#{home.welcome}">Welcome to our grocery store!</p>
</pre>
</p>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com1tag:blogger.com,1999:blog-28540858.post-68754502620221163472013-11-14T05:13:00.000-08:002013-11-14T05:13:15.114-08:00proxyconf 0.1.0 リリース add, useなどのサブコマンドを追加<p>
ターミナルのためのプロキシ切り替えコマンド"proxyconf"の0.1.0をリリースしました。
</p>
<ul>
<li><a href="https://github.com/daixque/proxyconf">Github : proxyconf</a></li>
</ul>
<p>
このリリースではadd, useなどのサブコマンドが追加され、ターミナルで任意のプロキシに素早く切り替えることができるようになりました。
基本的な使い方は<a href="https://github.com/daixque/proxyconf">GithubのREADM</a>Eと<a href="http://opentechnica.blogspot.jp/2013/11/proxyconf.html">前のブログ投稿</a>をみてください。
</p>
<h3>アップデート</h3>
旧バージョンを使っていた人は以下のコマンドでアップデートできます。
<pre class="prettyprint">
$ gem update proxyconf
$ proxyconf-setup update
$ source "$HOME/.proxyconf/proxyconf"
</pre>
<h3>通常の使い方</h3>
<p>
システムに設定されているプロキシを使う場合はproxyconfコマンドを実行するだけです。(旧バージョンから変わらず)
</p>
<pre class="prettyprint">
$ proxyconf
set proxy: yourproxy.com:8080
</pre>
<p>
これで環境変数のhttp_proxy, https_proxy, ftp_proxyに、今使っているネットワークに対してシステム環境設定で設定しているプロキシが設定されます。
</p>
<h3>任意のプロキシを設定して使う</h3>
<p>
addコマンドで任意のプロキシをproxyconfに登録し、useコマンドで設定したプロキシに切り替えることができます。
</p>
<pre class="prettyprint">
$ proxyconf add other other.proxy.com:8080
$ proxyconf use other
</pre>
<p>
addで登録したプロキシの一覧はlistコマンドで表示できます。またinfoコマンドで指定したプロキシの設定内容を確認できます。
</p>
<pre class="prettyprint">
$ proxyconf list
current
other
$ proxyconf info other
export http_proxy=other.proxy.com:8080
export ftp_proxy=other.proxy.com:8080
export https_proxy=other.proxy.com:8080
</pre>
<p>
登録したプロキシはremoveコマンドで削除できます。
</p>
<pre class="prettyprint">
$ proxyconf remove other
$ proxyconf list
current
</pre>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-1011614874022449042013-11-07T04:37:00.001-08:002013-11-07T04:37:36.975-08:00proxyconf : ターミナルのためのプロキシ切り替えコマンド<p>
proxyconfというターミナルのためのプロキシ切り替えツールをgemでリリースしました。
<ul>
<li><a href="https://github.com/daixque/proxyconf">Github : proxyconf</a></li>
</ul>
</p>
<p>
いつも仕事でMacを使っているとき、Ethernetケーブルでは会社のネットワークに、WiFiでは別のプロバイダのネットワークに繋がっているんですが、会社のネットワークではプロキシサーバーを通さなければ行けません。Macだとブラウザでネットをみるときにはシステム環境設定で設定してあるプロキシを自動的に使ってくれるので問題ないのですが、ターミナルでcurlのようなネット接続するツールを使うにはいちいち環境変数のhttp_proxyを設定しなければいけないのが面倒でした。
</p>
<p>
そこでターミナルでも現在のネットワークに対応したプロキシを自動的に設定するツールとしてproxyconfを作りました。
</p>
<h3>インストール</h3>
<p>
以下の手順でインストールしてください。
</p>
<pre class="prettyprint">
$ gem install proxyconf
$ proxyconf-setup
</pre>
<p>
proxyconf-setupコマンドで、~/.proxyconfディレクトリを作り、~/.bash_profileの最後にproxyconf用の設定を読み込むための一行を追加します。この設定は次にターミナルを開いたときから有効になります。インストールしたターミナルですぐに利用する場合は以下のコマンドをターミナルに入力してください。
</p>
<pre class="prettyprint">
$ source "$HOME/.proxyconf/proxyconf"
</pre>
<h3>使い方</h3>
<p>
単純にproxyconfコマンドを実行するだけです。
</p>
<pre class="prettyprint">
$ proxyconf
set proxy: yourproxy.com:8080
</pre>
<p>
これで環境変数のhttp_proxy, https_proxy, ftp_proxyに、今使っているネットワークに対してシステム環境設定で設定しているプロキシが設定されます。
</p>
<h3>アンインストール</h3>
<p>
以下のコマンドでファイルを削除します。
</p>
<pre class="prettyprint">
$ gem uninstall proxyconf
$ rm -rf ~/.proxyconf
</pre>
<p>
次に、以下の行を~/.bash_profileまたは~/.bashrcから削除してください。
</p>
<pre class="prettyprint">
[[ -s "$HOME/.proxyconf/proxyconf" ]] && source "$HOME/.proxyconf/proxyconf"
</pre>
<h3>対応OS</h3>
<p>
現時点ではMacにしか対応していません。今後、Linuxなら対応可能だと思います。Windowsは多分無理かな。一部bashを使っているので。
</p>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com1tag:blogger.com,1999:blog-28540858.post-12300297318694073682013-09-30T07:06:00.002-07:002013-09-30T07:06:53.655-07:00bundlerを使ったgemの作り方、公開方法<p>
Rubyのgemパッケージを作成する手順について。bundlerにgem作成を助ける機能がいくつかあるので利用する。
</p>
<h3>ひな形の作成</h3>
<p>
bundle gemでひな形を生成する。
</p>
<pre class="prettyprint">
$ bundle gem mylib
</pre>
<p>
gemspecは各gemごとに適当に修正する。ひな形を見ればすぐに内容はわかる。
</p>
<h3>依存ライブラリ</h3>
<p>
依存ライブラリはGemfileではなくgemspecファイルに記述して、Gemfileからはgemspecを参照するだけにする。
</p>
<h4>Gemfile</h4>
<pre class="prettyprint">
source 'https://rubygems.org'
gemspec
</pre>
<h4>mylib.gemspec</h4>
<pre class="prettyprint">
Gem::Specification.new do |spec|
...
spec.add_runtime_dependency "hashie"
spec.add_runtime_dependency "json"
spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
end
</pre>
<h3>ビルド</h3>
<p>
gem buildコマンドでビルド。
</p>
<pre class="prettyprint">
$ gem build mylib.gemspec
</pre>
<p>
bundleでひな形を作っている場合は、rake buildでpkgフォルダにgemパッケージが作成される。
</p>
<pre class="prettyprint">
$ rake build
</pre>
<h3>公開</h3>
<p>
gem pushコマンドで公開。このとき、rubygems.orgのアカウントが必要。
</p>
<pre class="prettyprint">
$ gem push mylib-x.x.x.gem
</pre>
<p>
同様にbundleでひな形を作っている場合は、rake releaseリリースできる
</p>
<pre class="prettyprint">
$ rake release
</pre>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com1tag:blogger.com,1999:blog-28540858.post-16868904275983976282013-09-24T05:32:00.000-07:002013-09-24T05:32:18.329-07:00Chrome App: JSON Pretty Printer をリリースしました<p>
<a href="http://opentechnica.blogspot.jp/2013/09/jsonpritty-printhtml.html">以前作った</a>JSONを整形するHTMLのツールをChrome Appとして公開しました。<a href="https://chrome.google.com/webstore/detail/json-pretty-printer/engmhjmhpefoikhobkahplacofaogiob?hl=ja">Chrome Web Storeに公開されています。</a>
</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://chrome.google.com/webstore/detail/json-pretty-printer/engmhjmhpefoikhobkahplacofaogiob?hl=ja" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl4x35tVV8zYkRljE2IX6vCSC277PNIzN0huRysmrXimVOMJvWZjN7gsyL5y1PSK835ava-VUBTzVjrLNEbL9BBeFRyz2zt3K_lpIG7pp_2LYPX-5vvj2y8zdA4avLoP7OKfbV8g/s400/prettyprinter-marquee.png" /></a></div>
<p>
ただ受け取ったJSONを整形するだけのもの凄くシンプルなツールですが、よければ使ってください。
</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUE1ZkOouTTvStUt1SEWlJ-s3aAQ1Z0Jbnqqclu_ccMha0bQovrBNntHIPlmNVcrjQp5yaL5MRY7aeGTJ_jtaz2S1kLcE5btAye3fdpzm_CcsJhBovHISyK61yxeLd066ppUJZjA/s1600/prettyprint-screenshot-02.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUE1ZkOouTTvStUt1SEWlJ-s3aAQ1Z0Jbnqqclu_ccMha0bQovrBNntHIPlmNVcrjQp5yaL5MRY7aeGTJ_jtaz2S1kLcE5btAye3fdpzm_CcsJhBovHISyK61yxeLd066ppUJZjA/s400/prettyprint-screenshot-02.jpg" /></a></div>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com1tag:blogger.com,1999:blog-28540858.post-66513316432236708152013-09-24T05:20:00.000-07:002013-09-24T05:20:45.920-07:00RubyでJSON/XMLをPretty Printするgem prettyprintファイルまたは標準入力から受け取ったJSON/XMLをインデント表示するRuby製のツールprettyprintをgemで公開しました。
<ul>
<li><a href="https://github.com/daixque/prettyprint">Github : PrettyPrint</a></li>
</ul>
<h3>インストール</h3>
<pre class="prettyprint">
$ gem install prettyprint
</pre>
<h3>使い方</h3>
<pre class="prettyprint">
prettyprint [json|xml] [filepath]
</pre>
<p>
gemでインストールするとprettyprintコマンドが使えるようになります。prettyprintコマンドはxmlまたはjsonというサブコマンドを持ちます。ファイル名を指定するとそのファイルを入力とします。
</p>
<pre class="prettyprint">
$ prettyprint json input.json
</pre>
<p>
ファイル名を省略すると、標準入力を受け付けます。
</p>
<pre class="prettyprint">
$ echo '<html><title>prettyprint</title><body>happy pretty printing</body></html>' | prettyprint xml
<html>
<title>
prettyprint
</title>
<body>
happy pretty printing
</body>
</html>
</pre>
<p>
</p>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com1tag:blogger.com,1999:blog-28540858.post-13387420724336185492013-09-06T22:46:00.001-07:002013-09-19T07:14:36.775-07:00JSONのPritty PrintするHTMLページを作った<p>
ちょくちょく必要になるのでHTML/JavaScriptでJSONをPritty Printするツールというかページを作りました。
</p>
<ul>
<li><a href="https://dl.dropboxusercontent.com/u/76095/jsonprittyprint/index.html">JSON Pritty Printing</a></li>
</ul>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhteLsdN70W85rm9oRZhlnFAsb1kSSVPfCZpf7ulDItLzT6DHQ-cLaz5BskaIjb9SyRs0qhKTMo-6IbAZuNbv-HBRMFR-Qdra2xQ8Q3Y6zDDccstiF8EIh5fM-jv7i0GyOAL3pGpg/s1600/JsonPrittyPrinting.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhteLsdN70W85rm9oRZhlnFAsb1kSSVPfCZpf7ulDItLzT6DHQ-cLaz5BskaIjb9SyRs0qhKTMo-6IbAZuNbv-HBRMFR-Qdra2xQ8Q3Y6zDDccstiF8EIh5fM-jv7i0GyOAL3pGpg/s320/JsonPrittyPrinting.png" /></a></div>
<p>
内容は単純に入力に対してJSON.stringifyしているだけ。おまけとして、zClipというクリップボード用jQueryプラグインを使って、出力結果をクリップボードにコピーできるようにしてある。prettyprintの部分はこんな感じ。
</p>
<pre class="prettyprint">
var src = $('#src').val();
var obj = JSON.parse(src);
var formatted = JSON.stringify(obj, undefined, 2);
</pre>
<p>
ちなみに前にも書いているけど、これを使わない場合はPythonのワンライナーでやっていいる。
</p>
<pre class="prettyprint">
$ echo '{"foo":"FOO", "bar": [1, 2, 3]}' | python -mjson.tool
{
"bar": [
1,
2,
3
],
"foo": "FOO"
}
</pre>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com1tag:blogger.com,1999:blog-28540858.post-8492083643414185552013-08-27T01:34:00.000-07:002013-08-27T01:34:02.727-07:00Rubyのワンライナーを使ってファイルの中で最も長い行を調べる<p>
表題の通り、以下の処理をするワンライナー。
<ul>
<li>target.txtを読み込んで</li>
<li>ユニークをとって</li>
<li>最も長い行(文字数)を調べ</li>
<li>長い順にソートして</li>
<li>先頭の5行を表示する</li>
</ul>
</p>
<pre class="prettyprint">
$ cat target.txt | uniq | ruby -ne 'puts sprintf("%03d %s",$_.chomp.size,$_)' | sort -r | head -5
</pre>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com1tag:blogger.com,1999:blog-28540858.post-9645650852040143362013-08-20T02:16:00.000-07:002013-08-20T02:16:36.967-07:00MySQLでMD5のハッシュ値を計算する<p>
今まで知らなかったが、MySQLではSQLで直接MD5のハッシュ値を計算できる。
</p>
<pre class="prettyprint">
mysql> select md5('test');
+----------------------------------+
| md5('test') |
+----------------------------------+
| 098f6bcd4621d373cade4e832627b4f6 |
+----------------------------------+
</pre>
<p>
ちなみにコマンドラインで計算する方法もいつも忘れるのでメモ。
</p>
<pre class="prettyprint">
# -sオプションの直後に変換する元の文字列を続ける
$ md5 -stest
MD5 ("test") = 098f6bcd4621d373cade4e832627b4f6
</pre>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-21842868069026232732013-08-19T06:41:00.001-07:002013-09-20T02:51:13.467-07:00Ruby製のテスト用メールサーバーmocksmtpdをBase64に対応<p>
仕事でメール送信の機能を作るとき、ダミーのSMTPサーバーが必要になり、kosekiさんによる<a href="https://github.com/koseki/mocksmtpd">mocksmtpd</a>というRuby製のものを見つけた。ただしBase64エンコードされたメールで日本語が表示できていなかったので、GithubでフォークしてBase64に対応した。あと、出力されるHTMLも若干変更しています。
</p>
<p>
<a href="https://github.com/daixque/mocksmtpd">daixque/mocksmtpd</a>
</p>
<h4>特徴</h4>
<ul>
<li>Ruby製のSMTPサーバー</li>
<li>受信したメールは転送せず、HTMLファイルに書き出す</li>
<li>Base64に対応</li>
</ul>
<p>
詳細な使い方は作者のkosekiさんのブログも参考に。
</p>
<p>
<a href="http://koseki.hatenablog.com/entry/20081103/mocksmtpd">開発用のメールサーバ mocksmtpd を gem にしてみた。</a>
</p>
<h3>インストール</h3>
<p>
今はGithubがgemのホスティングをやめているので、specific_installというgemを利用する。これを使うとGithubのソースから直接gemをインストールできる。
</p>
<pre class="prettyprint">
$ gem install specific_install
$ gem specific_install -l https://github.com/daixque/mocksmtpd.git
</pre>
<h3>起動</h3>
mocksmtpd initでmocksmtpdフォルダに設定ファイルなどを生成。そのままの設定でよければ、そのフォルダに移動してmocksmtpdコマンドを実行する。デフォルトでは25番ポートを使おうとするので、sudoが必要。メールを受信するとinboxフォルダにHTMLファイルが作られる。
<pre class="prettyprint">
$ mocksmtpd init
$ cd ./mocksmtpd
$ sudo mocksmtpd
</pre>
daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-45535223764292287412013-08-10T22:36:00.000-07:002013-08-10T22:36:45.268-07:00Spring MVCでアスペクト(インターセプター)を実装する<p>
Spring MVCでアスペクト(インターセプター)を実装するのは結構簡単。アスペクトっていうのは、要するにメソッドに対して前後処理をするモジュールのこと。フィルターみたいなやつですね。Springの場合はSpring配下にある任意のクラスのメソッドに適応可能。アスペクトで実装する一番ありがちな処理はログでしょうね。私もそのために使いました。あとはエラー処理とか。
</p>
<p>
SpringではどうもAspect Jを使ってAOPをしていて、用語もそれに従っている。ここでは面倒なので細かい用語の説明はなし。気になる人はアドバイス、ポイントカット、ジョインポイントあたりについて調べるといいんじゃないでしょうか。もっと色々ありそうですけど。
</p>
<h3>アスペクトの種類</h3>
<p>
アスペクトには以下の種類がある。
<ul>
<li>Before : メソッドの処理の前</li>
<li>AfterReturning : メソッドの処理の後例外は除く)</li>
<li>AfterThrowing : メソッドで例外が発生したとき</li>
<li>After : メソッドの処理の後(例外も含む)</li>
<li>Around: メソッドの前後処理を記述</li>
</ul>
単純なログならBeforeやAfter*、処理時間の計測とかを含むならAround、っていうのがありがちのようですね。
</p>
<h3>アスペクトのクラスを実装</h3>
<p>
すごい簡単。アスペクトのクラスに@Aspect、インターセプターの処理のメソッドに、種類に応じて上記の名前のアノテーション(@Beforeとか)をつけるだけ。
</p>
<p>
例えば、Service層のクラスの中で、自作の@UpdateDatasourceというアノテーションのついているメソッドのみ特定のログを出力したいときの例。ここで、サービス層はorg.opentechnica.sample.serviceパッケージにあるとする。
</p>
<p>
アノテーションは普通に実装。
</p>
<pre class="prettyprint">
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface UpdateDatasource {
public String value();
}
</pre>
<p>
アスペクトも、アノテーション以外は普通に実装。
</p>
<pre class="prettyprint">
@Aspect
@Component
public class LoggingAspect {
@Before("execution(public * org.opentechnica.sample.service..*(..))")
public void before(JoinPoint jp) {
try {
Class<? extends Object> targetClass = jp.getTarget().getClass();
String methodName = jp.getSignature().getName();
MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
UpdateDatasource updateDatasourceAnnotation = method
.getAnnotation(UpdateDatasource.class);
if (updateDatasourceAnnotation != null) {
Logger logger = Logger.getLogger(targetClass);
logger.info("before");
}
} catch (SecurityException e) {
// do nothing
}
}
}
</pre>
<h4>@Beforeアノテーション</h4>
<p>
@Beforeアノテーションでメソッドの実行前にインジェクションする処理であることを表している。アノテーションの引数("execution(public * org.opentechnica.sample.service..*(..))")は、この処理を実行する対象をフィルタリングする条件。ポイントカットっていやつですね。ここでの指定は以下のような意味。
<ul>
<li>publicで</li>
<li>任意の戻り値型で</li>
<li>org.opentechnica.sample.serviceパッケージ以下の任意のクラスの</li>
<li>任意の引数を持つ</li>
</ul>
</p>
<h4>対象のメソッドが目的のアノテーションを持つかどうか調べる</h4>
<p>
Javaは同一のメソッド名でも引数が違うと違うシグニチャになるので普通のリフレクションだと面倒だけど、beforeメソッドに渡されるJoinPointから、以下のようMethodSignatureにキャストすると直接取得できる。
<pre class="prettyprint">
MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
</pre>
で、methodがとれたらもうmethod.getAnnotation(UpdateDatasource.class)とすれば、自作の@UpdateDatasourceが付加されているかどうかわかる。
</p>
<h3>applicationContext.xmlでAOPの設定</h3>
<p>
アスペクトを実装したら、applicationContext.xmlに以下の一行を追加するだけで動く。便利!
</p>
<pre class="prettyprint">
<aop:aspectj-autoproxy/>
</pre>
daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-15731513696366423482013-08-10T19:50:00.001-07:002013-08-10T19:50:48.954-07:00jQueryでsubmitするとき、name属性があるとうまくいかない<p>
タイトルで全て。
</p>
<p>
jQueryを使ってフォームをsubmitするとき、submit要素にname属性ががあるとうまく動作しないようなので、使わないようにする。
</p>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-47803396396062548672013-08-10T19:47:00.001-07:002013-08-10T19:47:25.565-07:00jQueryでチェックボックス<p>
jQueryでラジオボタン/チェックボックスを操作するとき、attr("checked", "checked")だと2回目以降うまく動かないので、prop("checked", true)を使うのが正解。
</p>
<pre class="prettyprint">
// これはOK
$("input[type=radio]").prop("checked", true);
// こっちは2回目以降うごかない
$("input[type=raido]").attr("checked", "checked");
</pre>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-42651371358683318342013-03-29T09:13:00.000-07:002013-03-29T09:13:07.609-07:00Cameleon v0.1.1<h3>Cameleon v0.1.1リリース</h3>
<p>HTTPのスタブを作るためのフレームワークCameleonのv0.1.1をリリースしました。</p>
<a href="https://github.com/daixque/cameleon">Github : Cameleon</a>
<p>v0.1.1ではポストされたJSONをバリデーションする機能を追加しました。Cameleonはgemでインストールできます。</p>
<pre class="prettyprint">
$ gem install cameleon
</pre>
<p>使い方の詳細は<a href="http://opentechnica.blogspot.jp/2011/09/cameleon.html">前の記事</a>を参照してください。</p>
<h3>JSONバリデーション</h3>
<p>v0.1.1のJSONバリデーション機能では、POSTまたはGETのHTTPリクエストボディのJSONについて、データ構造の検証を行うことができます。バリデーションのエンジンには<a href="https://github.com/hoxworth/json-schema">json-schema gem</a>を利用し、<a href="http://tools.ietf.org/html/draft-zyp-json-schema-03">JSON Schema Draft 3</a>のスキーマ定義を利用します。このバリデーション処理をするには、まず設定ファイル(cameleon.yml)に以下の内容を記載します。</p>
<pre class="prettyprin">
validation:
type: json
</pre>
<p>その上で、レスポンスフォルダにrequest.schema.jsonというスキーマファイルをおいておくと、リクエストボディにそのスキーマに適合するJSONデータが含まれない場合にはステータス500のエラーが帰るようになります。</p>
<p>例えば次のようなJSONを期待するインターフェイスの場合</p>
<pre class="prettyprin">
{"a": 1}
</pre>
<p>次のようなスキーマを定義します。</p>
<pre class="prettyprin">
{
"type" : "object",
"properties" : {
"a" : {
"type" : "integer",
"required" : true
}
}
}
</pre>
daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-14817201762721159532013-02-23T01:16:00.000-08:002013-02-23T17:36:52.943-08:00Handling remote bare Git repository
<p>
When you have Git repositories as below.
<ul>
<li>CENTER.git : Central repository you can not manage</li>
<li>MAIN.git : Main repository that your team push into</li>
<li>LOCAL : Local repository on developers local machine</li>
</ul>
</p>
<h3>Merge on bare repository</h3>
<p>
You can't merge on bare repository such as MAIN.git because bare repository has no working copy. There are no ways to resolve the conflict when it occurs. Therefore, you must checkout the target branch into your local repository, merge your commits, then push to bare repository(MAIN.git).
</p>
<h3>Merge from external repository</h3>
<p>
Use 'git fetch' when there are some changes on CENTER.git. But this command doesn't update HEAD position. So you should use 'git reset --soft'.
<pre class="prettyprint">
# on MAIN.git
$ git fetch <CENTER.git>
$ git reset --soft HEAD
</pre>
check commit histories using 'git log'.
</p>
<h3>Push specified branch</h3>
<p>
You can push local branch 'dev-local' into 'dev-remote' on origin.
<pre class="prettyprint">
$ git push origin dev-local:dev-remote
</pre>
</p>
<h3>Clone from remote branch</h3>
<p>
You can checkout 'dev-remote' branch on MAIN.git into 'dev-local' branch on local machine:
<pre class="prettyprint">
git clone <MAIN.git>
git checkout -b dev-local remotes/origin/dev-remote
</pre>
</p>
<h3>Push tags into remote repository</h3>
<p>
You can push local tags into remote repository.
<pre class="prettyprint">
$ git push --tags
</pre>
</p>
<p>
This article is translated from <a href="http://opentechnica.blogspot.jp/2012/01/gitbare.html">Japanese</a>.
</p>
daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-76638715440955787492013-02-22T00:45:00.000-08:002013-02-22T00:45:11.230-08:00How to create new environment type (RAILS_ENV) for Rails3<p>
You know there are development, test and production environments on Ruby on Rails. This article shows you how to create new environment for your system.
</p><p>
We are currently working with:
</p><p>
<ul>
<li>Ruby: 1.9.2</li>
<li>Ruby on Rails: 3.0.5</li>
</ul>
</p>
<h3>How to refer environment name</h3>
<p>
You can refer environment name through <tt>Rails.env</tt>.
<pre class="prettyprint">
p Rails.env #=> "development"
</pre>
</p>
<h3>Adding new environment</h3>
<p>
For example, you can add your new 'staging' environment by these steps.
Follow these steps to add your new 'staging' environment.
<ol>
<li>copy RAILS_HOME/config/environments/production.rb as RAILS_HOME/config/environmentsstaging.rb</li>
<li>add staging section into database.yml</li>
</ol>
If you have any other configuration file, edit the configuration too.
</p><p>
Then, create database, do migration, and start your staging server.
<pre class="prettyprint">
$ rake db:create RAILS_ENV=staging
$ rake db:migrate RAILS_ENV=staging
$ rails server -e staging
</pre>
Yes! You now have new 'staging' environment for your project.
</p>
<h3>gem setting</h3>
<p>
You can use different gems for your each environment. This situation, write your Gemfile as below.
<pre class="prettyprint">
group :development, :test do
gem 'sqlite3-ruby'
end
group :staging, :production do
gem 'mysql2', '0.2.7'
end
</pre>
You can reject unnecessary gems for specified environment.
<pre class="prettyprint">
$ bundle install --without test development
</pre>
see: <a href="http://gembundler.com/groups.html">Bundler : Using Groups</a>
</p>
<p>
This article is translated from <a href="http://opentechnica.blogspot.jp/2012/01/railsenv.html">Japanese</a>.
</p>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-57615717350156604772013-02-21T01:27:00.000-08:002013-02-21T01:27:07.095-08:00httpstatus コマンドで、HTTP のステータスコードをすばやくしらべる! in Ruby<p>
なんだか流行っているようなので。
</p>
<p>
一般的な Web Programmer ならば、HTTP Status code はすべて暗記していると聞きました。しかし、僕は初心者なので、なかなか覚えきれていないので、HTTPのステータスコードをさがすのに便利なツールを用意しました。Rubyで書いてます。<a href="https://github.com/daixque/httpstatus">Github</a>に上げてあります。
</p>
<pre class="prettyprint">
$ httpstatus 40
400: Bad Request
401: Unauthorized
402: Payment Required
403: Forbidden
404: Not Found
405: Method Not Allowed
406: Not Acceptable
407: Proxy Authentication Required
408: Request Timeout
409: Conflict
$ httpstatus bad
400: Bad Request
502: Bad Gateway
</pre>
インストールはgemで。
<pre class="prettyprint">
$ gem install httpstatus
</pre>
元ネタなど。
<ul>
<li><a href="http://blog.64p.org/entry/2013/02/21/121830">httpstatus コマンドで、HTTP のステータスコードをすばやくしらべる! (perl)</a></li>
<li><a href="http://yuroyoro.hatenablog.com/entry/2013/02/21/144004">httpstatus コマンドで、HTTP のステータスコードをすばやくしらべる! (Haskell)</a></li>
<li><a href="http://blog.livedoor.jp/dankogai/archives/51855038.html">javascript - httpstatus.js</a></li>
</ul>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-75981385782987834682013-02-07T21:02:00.000-08:002013-02-08T02:09:59.026-08:00CentOS, Redmine, ImageMagick, RMagick<p>
CentOSにRedmineをインストールするために、ImageMagickとRubyバインディングのRMagickをインストールしたけど、やたら嵌ったのでメモ。なんか前からImageMagickのインストールはすんなり行ったことがないような。
</p>
<p>
まずはyumでインストールしようとしたけど、バージョンが古いのでNG。本家からRPMでインストールしてもエラーが出てNG。多分ヘッダーとかのパスの問題っぽいが、ImageMagick-develみたいなものをRPMでどう認識させて良いかわからず断念。(後から考えると、このタイミングでPKG_CONFIG_PATHを設定すればうまく行ったのかも)
</p>
<p>
最終的には本家からソースを持ってきてインストールして、PKG_CONFIG_PATHを設定した後にRMagickをインストールするとうまく行った。
</p>
<pre class="prettyprint">
$ tar xzvf ImageMagick.tar.gz
$ cd ImageMagick-6.8.2-6/./configure
$ make
$ sudo make install
$ sudo /sbin/ldconfig /usr/local/lib
$ gem install rmagick -v '2.13.2'
</pre>
<p>
Bundlerでライブラリが取得さえできれば、Redmineのインストールは特に問題なし。
</p>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-90096065082735737282013-01-08T03:20:00.000-08:002013-01-08T03:20:18.023-08:00RubyのTwitter gemでrate_limit_statusを取得<p>
Rubygemsにあるtwitterバージョン4以降は、rate_limit_statusを取得するAPIがなくなった。これは、このAPIの利用方法がTwitterのREST APIのエンドポイントURIに依存していて、Twitter側の仕様変更があったとき、このAPIをサポートしているとライブラリの更新だけで(アプリの修正なしに)この変更に追随することができなくなるためらしい。
</p><p>
まあ設計思想としては理解できるが、とはいえこのライブラリを使ってやりたいことはTwitterのREST APIを叩くことだから、Twitter側の仕様変更に影響を受けることはある程度は仕方ないと思うんだが、どうだろうか。もちろんそこが隠蔽されていて、Twitter側のバージョンが変わってもアプリのコードに変更がない、ということが可能であれば美しいけど。
</p><p>
で、無理やりrate_limit_statusを取得するには以下のコード。
</p>
<pre class="prettyprint">
Twitter.get('/1.1/application/rate_limit_status.json')[:body]
</pre>
<p>
要するにgetというメソッドを使えば、直接使いたいAPIを叩ける。このコードで結果がHashで返ってくる。
</p>
参考)<a href="https://github.com/sferik/twitter/issues/318">https://github.com/sferik/twitter/issues/318</a>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-45438140948746574052012-11-16T23:40:00.000-08:002012-11-16T23:40:22.919-08:00mmrd (MongoDB MapReduce Driver) リリースしました<p>
MongoDBのMapReduceをNode.jsから実行/テストするためのモジュール、<strong>mmrd</strong>をリリースしました。
</p>
<ul>
<li>mmrd: <a href="https://github.com/daixque/mmrd">https://github.com/daixque/mmrd</a></li>
</ul>
<h3>インストール</h3>
<pre class="prettyprint">
$ npm install mmrd
</pre>
<h3>使い方</h3>
<p>
例えばMongoDBのワードカウントなどで、以下のようなMapReduceを書いていたとします。
</p>
<pre class="prettyprint">
// map.js
function map() {
var words = this.text.split(' ');
words.forEach(function(word) {
emit(word, 1);
});
}
</pre>
<pre class="prettyprint">
//reduce.js
function reduce(key, values) {
var result = 0;
values.forEach(function(v) {
result += v;
});
return result;
}
</pre>
<p>
このとき、mmrdを使うと以下のような形でこのMapReduceをNode.jsから実行できます。
</p>
<pre class="prettyprint">
// runner.js
var mmrd = require('mmrd');
// map test
(function() {
console.log("Word count / Map test");
var doc = { text: "foo bar baz" };
mmrd.loadMap('map.js');
mmrd.map(doc, function(key, value) {
console.log(key, ":", value);
});
})();
// reduce test
(function() {
console.log("Word count / Reduce test");
mmrd.loadReduce('reduce.js');
var key = "foo";
var values = [1, 1];
var reduced = mmrd.reduce(key, values);
console.log(key, ":", reduced);
})();
// integration test
(function() {
console.log("Word count / Integration test");
var docs = [
{ text: "foo bar baz" },
{ text: "foo baz baz"}
];
mmrd.loadMap('map.js');
mmrd.loadReduce('reduce.js');
var result = mmrd.mapReduce(docs);
console.log(result);
})();
</pre>
起動
<pre class="prettyprint">
$ node runner.js
</pre>
<p>
もちろん、mochaやshouldを使ったテストも書けます。当たり前ですが。
</p>
<p>
お試しあれ。
</p>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-87681939079799772942012-10-16T22:17:00.000-07:002012-10-16T22:19:27.348-07:00Rubyで短縮URL(リダイレクトされるURL)からコンテンツを取得する<p>
短縮URLは普通リダイレクトで目的のコンテンツまで辿り着く。Rubyで短縮URLで指定されたコンテンツを扱いたいが、http_clientはリダイレクトには対応しているけど、デフォルトではhttpsの短縮URLに対してhttpのURLにリダイレクトされたときに例外を吐くのでbit.lyなんかではうまく使えない。
</p>
<p>
なので、以下のように常にリダイレクトするようにコールバックを設定すると、この制限を回避できる。
</p>
<pre class="prettyprint">
require 'httpclient'
def get_content_with_redirection(url)
client = HTTPClient.new
def client.allow_all_redirection_callback(uri, res)
urify(res.header['location'][0])
end
client.redirect_uri_callback = client.method(:allow_all_redirection_callback)
client.get_content url
end
html = get_content_with_redirection("http://bit.ly/RRKD7d")
puts html
</pre>daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0tag:blogger.com,1999:blog-28540858.post-74167633469583178042012-09-24T08:00:00.000-07:002012-09-24T08:00:11.965-07:00fluentdのインストールと簡単な使い方<p>
<a href="http://fluentd.org/">fluentd</a>はRubyで書かれたsyslogdのようなロギングミドルウェア。様々なログをネットワーク上で色々ルーティングして、たとえば最終的にMongoDBに登録したりすることができる。
</p>
<p>
fluentdをインストールして使ってみる。
インストールはgemで一発。
</p>
<pre class="prettyprint">
$ gem install fluentd
</pre>
<p>
fluentdを起動するには、作業ディレクトリを作ってコマンドで設定ファイルを作成する。起動はfluentdを-cオプションでキックする。
</p>
<pre class="prettyprint">
$ fluentd --setup ./fluent
$ cd fluent
$ fluentd -c conf/fluent.conf
</pre>
<p>
動作確認は別コンソールで次のように打ち込むと、先ほどのコンソールにログが出力される。
</p>
<pre class="prettyprint">
$ echo '{"json":"message"}' | fluent-cat debug.test
</pre>
<p>
ここまでは公式サイトと同内容。
次に、テキストファイルをtailのようにウォッチして、fluentdに転送してみる。
conf/fluent.confを次のように記述する。
</p>
<pre class="prettyprint">
<source>
type tail
path /path/to/test.log
tag debug.*
format /^(?<log>.*)$/
</source>
<match debug.**>
type stdout
</match>
</pre>
<p>
ここで、sourceディレクティブのtagはどのmatchディレクティブにログをルーティングするかを決めるためのキーとなる。RabbitMQのルーティングキーと同じ感じ。formatディレクティブは、出力形式を正規表現で設定する。このとき、マッチした箇所に?<name>で名前を付ける。上記例だとlogという名前にしてる。
</p>
<p>
この状態でfluentdを起動して/path/to/test.logに追記すると、コンソールにログが出力される。
</p>
<pre class="prettyprint">
$ echo test >> /path/to/test.log
</pre>
daixquehttp://www.blogger.com/profile/11315765687319271972noreply@blogger.com0