tag:blogger.com,1999:blog-91786207296278084462024-03-19T11:43:54.186+09:00Yakitarahiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.comBlogger73125tag:blogger.com,1999:blog-9178620729627808446.post-36435505401726595732014-03-09T11:05:00.000+09:002014-03-09T11:05:03.958+09:00What I thought after reading “Welcome to the Quiet Revolution”<a href="https://www.freelancersunion.org/blog/2014/02/27/welcome-quiet-revolution/">“Welcome to the Quiet Revolution”</a>
<blockquote>
Money equals time. It’s that simple. Each dollar you earn translates to time you weren’t spending with your family, friends or following a side passion. So, spending the money you earn means, really, spending your time.
</blockquote>
<blockquote>
(労働)収入は自分や家族のために使えたはずの時間を犠牲にして得ているということなので、お金を使うということは「自分の時間消費」することに等しい。
</blockquote>
<p>
“Quiet Revolution” とは、
つまり、働くために時間を使うにしても、それで得た収入を使うにしても、賢く使わないともったいないよね。ということらしい。
</p>
<p>
他にも要素はいろいろあるにしても、僕がフリーランスになった一番の動機は、「自分の自由に使える時間を増やしたい」ということなのでこのへんは同感ですね。
</p>
<p>
ちょうどいま、シゴトが忙しくてオレオレプロジェクトをやってる心の余裕がない状況なので、余計に考えさせられます。
そのシゴトは僕が長い間関わっているプロジェクトで、数ヶ月前から、いろいろ改善しましょうという時期に来ていて、僕が「全部捨てて書き直しましょう」みたいなことを言い出してしまったので自業自得なところもあるし、「こうしたい」的な感じで実装できているので、まあ楽しいし、落ち着けばあとで楽になるはずという希望もあるので、ある意味「自分のために」やっている部分もあるのですが。
</p>
hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-14933916248675774812013-10-06T20:34:00.001+09:002013-10-06T20:34:37.838+09:00au 携帯のメール受信を pebble に通知する方法みんな大好きバッドノウハウ。
<p>iPhone のロック画面に表示される通知が <a href="https://getpebble.com">Pebble</a> に通知されるハズなのですが、<a href="http://forums.getpebble.com/discussion/comment/62480/#Comment_62480">うまくゆかない</a>ので、 Pebble iOS アプリの "Email Notifications" を設定したいけど、 au の携帯メール(EZWebメール)はたぶん IMAP 設定できないし、できたとしてもパスワードを Pebble アプリで入力したくないので、携帯メールの転送先として新しく GMail アカウントを作成して、その GMail アカウントを Pebble の Email Notification として設定しました。</p>
具体的には、
<ol>
<li><a href="https://accounts.google.com/SignUp">新しい Google アカウントを作成</a></li>
<li><a href="http://www.au.kddi.com/iphone/iphone5/support/guide/email-ezweb-setup.html">EZwebメール各種設定</a>で作成した Gmail のアドレスを転送先として設定</li>
<li>Pebble iOS app の "Email Notification" 設定で Gmail アカウントを設定</li>
</ol>
<p>ちなみに、現状の Pebble では ASCII 7bit 以外の UTF-8 にはフォントの glyph が無いので豆腐になってしまいますので、メールの件名や本文が日本語だと、とりあえずメールが来たということしかわかりません。
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6tbOI9PjgqDelb61nmbq9uH9eMpZEJEDj6bkGge_oPtHeoLJnMUQ5RjfFjdHXFcvrP5JHE6tBF1XjKMj96oK4aGx6wJZJrgFd-5xw42XE_GRg6MP-6pSEbhRMpT3KYTVYJwVvW2E5JnlK/s1600/70ac64bba118410a193514795d5eb66b.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6tbOI9PjgqDelb61nmbq9uH9eMpZEJEDj6bkGge_oPtHeoLJnMUQ5RjfFjdHXFcvrP5JHE6tBF1XjKMj96oK4aGx6wJZJrgFd-5xw42XE_GRg6MP-6pSEbhRMpT3KYTVYJwVvW2E5JnlK/s320/70ac64bba118410a193514795d5eb66b.png" /></a>
また、 Pebble への通知はリアルタイムには来ないですね。ポーリングしてるのかな?
</p>
利用した環境は
<ul>
<li>Pebble iOS app 1.2.1</li>
<li>Pebble Firmware 1.12.1</li>
<li>iPhone 5 (iOS 7.0.2)</li>
</ul>
hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com1tag:blogger.com,1999:blog-9178620729627808446.post-13739798894306027242013-09-21T22:37:00.000+09:002013-09-21T22:37:47.048+09:00The localization bookmarklet<p>ネットで海外の情報を見るときに英語という言葉の壁もあるのですが、"Sep 11, 2013, 4PM US/Pacific" のような時差やサマータイムがあって日本時間で何時なのか分からないという問題と、 "1,000 lbs" のような単位系が違うのでどんだけ重いのかピンと来ないという問題がありますよね。</p>
<p>Google Translate とかでも "2013年9月11日、午後4時米国/太平洋", "1,000ポンド" みたいな「翻訳」はしてくれるのですが、「ローカリゼーション」はしてくれません。</p>
<p>そういうときに "Sep 12, 2013 08:00 JST" や "~454.00 kg" のような変換をして表示してくれるブックマークレットを作ってみました。</p>
<a href="http://hiroshi.github.io/l10nb9t/">http://hiroshi.github.io/l10nb9t/</a><br />
<p>気に入っていただけたら、 <a href="https://github.com/hiroshi/l10nb9t">github リポジトリ</a> で star したり、 tweet したりして頂けると嬉しいです。あ、要望とかバグ報告は日本語でもいいので <a href="https://github.com/hiroshi/l10nb9t/issues">https://github.com/hiroshi/l10nb9t/issues</a> にお願いします。</p>
<br/>
<p>P.S.1. 個人的な意見ですが、海外のメディアの日本語訳しているサイトでそういう時差や単位の変換をしていない翻訳はイラっと来ますね。もっと言うと文化的に理解できない内容や日本では利用できないサービスに対する訳注も無いやつはダメですね。お前は機械翻訳かと思います。</p>
<p>P.S.2. ブログ書くの久々ですね。一年半ぶりくらい。
<ul>
<li>どうでもいいことは twitter</li>
<li>技術的なことは stackoverflow</li>
<li>バッドノウハウ的なことは qiita</li>
</ul>
という感じで書く機会が無かったのですが、なにか自分でつくって告知したいけど Hacker News に Show HN するには怖いなというときはやっぱり自分のブログに落ち着く感じですかね。読者ほぼゼロだと思いますが...。他によいメディアを知らない。</p>
hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-4519378703390085272012-01-27T01:28:00.000+09:002012-01-27T02:05:57.852+09:00iOS App PhotoHistory Released!<div class="separator" style="clear: both; text-align: center;">
<a href="http://itunes.apple.com/jp/app/textlists/id473228750" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"><img border="0" height="175" width="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsAOJ4BSfHkM2dpqB4xkNkVNfsvbidGohyqbTq6rQXZdA9hMPzXw7aUUkmVPCt7_WMNrRV34GuMPQNxhwtdhShKA1lGqlTwj-Q_4AS7dV3ejXIL5bA1-8Oyh5kb8H-aiokVn3EANX9gSKO/s200/mzl.rhsrowbb.175x175-75.jpg" /></a></div>
<h3>iPhone / iPod Touch アプリ <a href="http://itunes.apple.com/jp/app/textlists/id473228750">PhotoHistory (Apple App Store 170円)</a> をリリースしました</h3>
<p>このアプリは僕自身が Apple 標準の写真アプリを使ってみて不便に感じたところを解決しようとしている試みです。何が問題かというと、「iPodTouch のカメラで撮った写真やデジカメなどからの大量の写真を整理せずに iOS に放り込むと、スクロールして写真を探すのは不可能」ということです。</p>
<p>大量の情報を扱う可能性のあるアプリの例としては、「連絡先」や「ミュージック」があります。これらのアプリは一覧の右側の「インデックス」により素早く目的のものを見つけることができます。PhotoHistory は写真の日付をインデックスにして、例えば「2008年のクリスマス」に瞬時に戻ることができます。</p>
<h3>I released iPhone / iPod Touch App <a href="http://itunes.apple.com/en/app/textlists/id473228750">PhotoHistory (Apple App Store $1.99)</a></h3>
<p>The PhotoHistory is designed to solve a problem when I used Photo.app of Apple. What's wrong with Photo.app? Photo.app is pretty simple and I was content till I had thousands of photos in my device. It is almost impossible to find a photo by scrolling and keep watching. Yes, I should organize photos in albums or events, but I wouldn't.</p>
<p>On the other hand, some apps possibly to manage lot of informations or data, say Music.app and Contacts.app, have "index" on the right side of their table interface. PhotoHistory simply use same design by "index" dates of photos. Now you can find "Christmas 2008" in an instant.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimHyGWF8AtLpetihEx1821DpBgiwcwfLALmosSBn7SJ1FPjKfTx-CDd0DMyHQli_gV4RyMF8J3E3F7wUppWbELxdGQN1630sOKZ1mbcm0fJCCb0cMpjQ6f79gnILQUYg5EP_uAiLEeC7dk/s1600/mzl.qawjowii.320x480-75.jpg" imageanchor="1" style=""><img border="0" height="200" width="134" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimHyGWF8AtLpetihEx1821DpBgiwcwfLALmosSBn7SJ1FPjKfTx-CDd0DMyHQli_gV4RyMF8J3E3F7wUppWbELxdGQN1630sOKZ1mbcm0fJCCb0cMpjQ6f79gnILQUYg5EP_uAiLEeC7dk/s200/mzl.qawjowii.320x480-75.jpg" /></a>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK2z8SR-gie3bMl0uPCz-yCVxvftc_09GRBH1H9J9XID4hjcv-ZOtlgPIS4SqcDOFoLcDKrFswQHRNjsjHmnRaWyUfW5M-slSLtSa3BO8Czn_PSIx58r4EAfo7zeoLe4SxeBWb8DdqgqIZ/s1600/mzl.lfrqiofx.320x480-75.jpg" imageanchor="1" style=""><img border="0" height="200" width="134" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK2z8SR-gie3bMl0uPCz-yCVxvftc_09GRBH1H9J9XID4hjcv-ZOtlgPIS4SqcDOFoLcDKrFswQHRNjsjHmnRaWyUfW5M-slSLtSa3BO8Czn_PSIx58r4EAfo7zeoLe4SxeBWb8DdqgqIZ/s200/mzl.lfrqiofx.320x480-75.jpg" /></a>
<div style="clear: both; text-align: center;">
<a href="http://itunes.apple.com/jp/app/textlists/id473228750" imageanchor="1" style="clear:right; float:right; margin-left:1em; margin-bottom:1em"><img style="border:0;" height="61" width="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6fyOeP9aLXj59bGom3C0DXH6p-nwpjFuUTNqy3ycl6mI3kwNi6DHmNVThXXvWZaLO1YWYdnu2A7ElVAS10QJKcNMCrKlL99lWRlH5-WY36TxfpMTtbpK4mELEreKIq8t9-JRxHcVLZezI/s400/as_available_appstore_icon_20091006.png" /></a></div>hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-68159318520820458012012-01-05T00:05:00.000+09:002012-01-05T00:11:54.315+09:00Synching Address Book on Lion, GMail Contacts and an Android<p>Mac (Lion) のアドレスブックと Gmail の Contacts と Android の連絡先を同期させるという基本的な作業が結構難しかったので書いときます。</p>
<p>まずは Lion のアドレスブックと GMail Contacts を同期させるには、<br/>
<blockquote>アドレスブックの環境設定 -> アカウント -> この Mac 内 -> アカウント情報 -> Google と同期 -> 構成</blockquote> でアカウント情報を入力して OK すると、mac の メニューバーに sync アイコンが表示され、メニューから「今すぐ同期」を実行すると Google Contacts と同期が取れます。
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLQqfzefG1GbNhB_6LvrpRD2C8xoI5OwIba5spXhw2GZTh3imC7IZ475J-3AThyEaGOoCMzmqiDVXPkBwXpnp9-c9dY_t_hjxfkeQdd9UCGyimDBhjxpo-moE3IydSrJs2c2PT7KLgmUKA/s1600/syncmenu.png" imageanchor="1" style=""><img border="0" height="61" width="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLQqfzefG1GbNhB_6LvrpRD2C8xoI5OwIba5spXhw2GZTh3imC7IZ475J-3AThyEaGOoCMzmqiDVXPkBwXpnp9-c9dY_t_hjxfkeQdd9UCGyimDBhjxpo-moE3IydSrJs2c2PT7KLgmUKA/s400/syncmenu.png" /></a></div>
</p>
<p>過去にアドレスブックと Gmail Contacts をインポート/エクスポートでコピーしてた場合など、単純に同期を開始するとダブったりするので、
<ul>
<li>アドレスブックか Gmail Contacts のどちらかがゴミならバックアップをとってから全部削除 (僕の場合、 Gmail Contacts がゴミだったので削除してから同期させました)</li>
<li>両方とも活かしたいなら、同期させてから、 Gmail Contacts で2つ以上のコンタクトをチェックしてから、 More メニューで "Merge Contacts" でまとめる</li>
<li>アドレスブックにも「選択したカードを結合」というメニュー項目があるので同じようなことができるかもしれません(試してませんが)</li>
</ul>
</p>
<p>Gmail Contacts の内容がマトモになったら、 Android の設定 -> アカウント から同期するようにチェックすればいいのですが、<a href="https://motorola-global-portal.custhelp.com/app/answers/detail/a_id/48525/~/droid-x---google-synchronization">Motorola の端末だと "Power Control widget" というやつで sync を off にしてると自動では同期できなくなるようです。</a> Android 端末のカスタマイズっぷりを把握してないので Motorola 以外の端末にもあるのかもしれませんが、不明。</p>
<p>実行環境は
<br />
<ul>
<li>Mac OS X Lion 10.7.2</li>
<li>au / Motorola PHOTON / Android 2.3.4</li>
</ul>
</p>
<p>ちなみに、アドレスブックと iOS 端末も iCloud で同期できるのですが、
アドレスブックの「アカウント情報」のヘルプには<br />
<blockquote class="tr_bq">
「iCloud アカウントを追加するきに Google 連絡先との同期が入になっている場合、その同期オプションは切になります。iCloud 連絡先サービスを利用している間は、その同期オプションを切にしておくことをお勧めします。」</blockquote>
と書いてあって怖いので試してません。</p>hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com1tag:blogger.com,1999:blog-9178620729627808446.post-19937184485530449352011-12-01T14:02:00.001+09:002011-12-02T09:37:28.337+09:00make testflight<p>
Xcode の Organizer を使って IPA を生成してから、ブラウザからアップロードするのは面倒なので、ネット上には <a href="https://testflightapp.com/api/doc/">Testflight upload API</a> を使ってアップロードを自動化するスクリプトはいくつか転がっていますが、 xcarchive のパス, Code sign identity, API token, Team token などの設定が自動化されていないのしか見つけれられなかったので Makefile を書いて見ました。
</p>
<h4>特筆すべき必要条件</h4>
<ul>
<li>Xcode 4 の設定項目についてのある程度の知識</li>
<li>ruby 1.9.x or `gem install json`</li>
</ul>
<h4>準備</h4>
<p>Build Phases の最後に "Run Script" を追加。</p>
<script src="https://gist.github.com/1413798.js?file=RunScriptPhase.sh"></script>
<p>ここで CODE_SIGN_IDENTITY を Makefile から参照するためにファイルに保存しているのですが、 "Automatic Profile Selector" を利用している場合は、 CODE_SIGN_IDENTITY の値は "iPhone Distribution" だけで署名者名が入らないので、固有の Identity を選択するようにしてください。</p>
<p>Xcode scheme の "Archive" build action の Post-actions に "Run script" を追加。</p>
<script src="https://gist.github.com/1413798.js?file=PostArchive.sh"></script>
<p>通常 scheme は "shared" しない設定にしてリポジトリに追加しないようにしていると思います。なので、この Post-action を設定する scheme は "XXX-testflight" みたいな名前で "duplicate" して "shared": on, "show": off にしてリポジトリに追加すると、共有できて Xcode の scheme 選択からも見えなくなるのでいいかと思います。</p>
<p>あとは、プロジェクトのディレクトリに Makefile を置いて、 `make testflight` を実行するだけです。 Testflight のノートを入力するフォームが開くのでノートを変更して配信先を選択してください。</p>
<p>初回実行時には "Team Token" と "API Token" の入力を要求されるので、ブラウザに Testflight のセッションが残っていれば、表示されるはずなのでコピペしてください。</p>
<p>Xcode の archive から実行したい人は、 Makefile を fork して工夫してみてください。</p>
<script src="https://gist.github.com/1413798.js?file=Makefile"></script>hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-38415374203070055062011-07-14T11:41:00.005+09:002011-11-26T21:40:33.634+09:00iOS autoresizing UIView TIPS2011-11-26: 根本的に理解が足りない気がしてきた。 autoresizingMask や layoutSubviews を使えば済む場合が多いはずなので整理ができたらまとめます。<br />
2011-10-04: view controller を window に直接 addSubview するのでなく UINavigationController や UITabBarController 配下にするばあいは viewWillAppear でも orientation は反映されているようなので、あとで調べて情報を更新したい<br />
2011-08-05: orientation が landscape の場合には - didRotateFromInterfaceOrientation: まで待つ必要があったので修正<br />
<br />
InterfaceBuilder を使わずにコードで iOS の view 階層を作成して画面サイズや orientation にあわせて autoresize させるにはいろいろと注意が必要になるのですが、イマイチ情報が無かったのでわかったことを書いておきます。<br />
<br />
ポイントとしては、 <a href="http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/BasicViewControllers/BasicViewControllers.htm" target="_blank">Apple のドキュメント "View Controller Programming Guide for iPhone OS" (rev. 2010-05-03) の "Custom View Controllers"</a> だと、コードで view 階層を作成するには loadView でやれみたいに読めるのですが、 loadView や viewDidLoad のタイミングでは autoresize はまだ反映されず、 viewWillAppear のタイミングで反映されるようです。<br />
さらに、 orientation が landscape (ヨコ) の場合には viewWillAppear ではダメで didRotateFromInterfaceOrientation: まで待たないとダメなようです。<br />
<br />
ちなみに、 orientation が viewController.view に反映されているかどうかは、 view.transform に rotation の値が入ってるかどうかで分かるようです。<br />
<pre><UIView: 0x5b59d80; frame = (20 0; 748 1024); transform = [0, -1, 1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x5b532a0>></pre>
<br />
<br />
従って、画面のサイズ(iPhone or iPad)、 navigation bar などの表示の有無 によって autoresize される view の frame や bounds に反映されるのは viewWillAppear のタイミングなので、例えば、それらの autoresize される view の subviews として view をグリッド状に並べたりするのは viewWillAppear でやれってことになります (orientation が portrait でないときは didRotateFromInterfaceOrientation)。<br />
<br />
ちなみに、 loadView で生成して addSubview する view をおまかせで画面に fit させる場合、<br />
initWithFrame する必要は無く、 frame は (0 0; 0 0) で OKのようです。<br />
<pre>- (void)laodView
{
UIView *rootView = [[[UIView alloc] init] autorelease];
rootView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.view = rootView;
}</pre>
<br />
<br />
逆に fit させる大きさ(この場合、navigation bar などを除いたサイズ) より大きい frame を設定してしまうと autoresize はうまくゆかないようです。<br />
<br />
また、 [super loadView] で自動生成される view は [[UIView alloc] init] した view とは違い、そのタイミングでの (orientation の反映されていない) frame になっていたり、プロパティの値が違うのか、期待どおりの動きにするのが面倒な感じなので自前で [[UIView alloc] init] したほうがよさそうです。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-80847987157066364082011-05-22T23:02:00.002+09:002012-01-14T22:44:23.700+09:00Rails 3.1 HTTP Streaming and content_for in controller<p>2012-01-14: <a href="https://github.com/clmntlxndr/content_for_in_controllers">content_for_in_controllers を gem</a> にしてくれた人がいます。 thanks!</p>
<a href="http://weblog.rubyonrails.org/2011/5/22/rails-3-1-release-candidate">Rails 3.1</a> では HTTP Streaming が導入されますが、 stream ON だと template と layout の処理順序がいままでの rails のように template -> layout ではなく layout 前半 -> template -> layout 後半 という自然な流れになるのですが、 content_for が絡むとややこしいことになります (詳しくは <a href="https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/streaming.rb">action_controller/metal/streaming.rb</a> のコメントを参照)。<br /><br />この関係で、 layout 前半で content_for :bar が先に実行されていることを期待した yield :bar が空振りしないように、 layout 前半で yield :bar などが実行されると stream であるのにも係わらず template が先に実行されます。このジレンマを緩和するために provide というヘルパーが導入されて、 provide :bar されると、以降の template の処理を中断して layout 前半を処理しているようです。<br /><br />もうこうなると stream ON のときは content_for は使わないで、 controller で <code>@title = "foo" </code> とかやってしまいそうになるので、 content_for を controller でも実行できるようにしてみました。 rails 2.X, 3.0 で使っていたやっつけ実装なのですがいちおう rails 3.1 でも動くことは確認しました。<br /><br /><script src="https://gist.github.com/985457.js?file=gistfile1.rb"></script><br /><br /><script src="https://gist.github.com/985457.js?file=gistfile2.rb"></script><br />みたいな感じで使います。<br /><br />あと HTTP Streaming に関しては、<br />いままでは view のベンチマーク結果に DB の負荷が混ざらないためにも DB アクセスは action 内で実行されるようにしてたけど stream の場合 view のレンダリング中に DB アクセスが実行されるようにしたほうがよいことになりますね。(ソースのコメントにもかいてありますけど。)<br /><br />また、HTTP Streaming は ruby 1.9 の Fiber が使われているので、 <a href="http://yehudakatz.com/2010/05/05/ruby-1-9-encodings-a-primer-and-the-solution-for-rails/">Encoding の問題が煩わしくて</a> ruby 1.9 にする必要性が感じられない場合に ruby 1.9 導入のきっかけになるといいですね。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-57210892001339445702011-05-02T16:41:00.003+09:002012-02-02T23:06:40.785+09:00processing png<p>2012-02-02: processing.js へのリンクが切れて画像が生成されなかった問題を修正</p>
web や iOS app の開発をしているときにボタンとかに使うチマチマした画像が必要なことがあります。いままでは <a href="http://seashore.sourceforge.net/The_Seashore_Project/About.html">Seashore</a> でドットを打ったりしてましたが、 <a href="http://processingjs.org/">Processing.js</a> を使うとプログラムで簡単に絵を描くことができるので、プログラマとしては色やサイズの微調整とかの応用がしやすいですね。<br />
<br />
以下は iframe に展開したデモです。 m とか s の値を変えて update すると更新されるのがわかるかと思います。<br />
<iframe height="400" src="http://dl.dropbox.com/u/348426/processing_png.html" width="500"></iframe><br />
<br />
基本的には <a href="http://processingjs.org/learning/ide">Processing.js Web IDE</a>の簡易版ですが、 canvas の内容を img タグに画像としてコピーしているので、その画像をファイルとして保存すれば素材として使えます。<br />
<br />
現状、ワークフロー的にはローカルリポジトリのファイルとブラウザ上の textarea, img との手作業のコピペが何度も発生するので洗練されてませんが、工夫すればもうちょっとマシになるかもしれません。<br />
<br />
<a href="https://gist.github.com/951256">ソースのhtml</a>は gist にあります (<a href="https://gist.github.com/raw/951256/5a93e4b67a3a5e7475c12ec3a21a9b5a239565a2/processing_png.html">raw</a> を iframe の src に指定すると text/plain になっちゃってダメなので dropbox のファイルを参照)hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-47452197397202824102011-04-19T22:42:00.004+09:002011-04-19T23:08:20.814+09:00goo.gl Automator serviceMac で選択したテキストのURL短縮できると便利だと思って、<a href="http://www.google.com/search?client=safari&rls=en&q=mac+os+x+サービス+URL短縮&ie=UTF-8&oe=UTF-8">調べてみると</a> <a href="http://code.google.com/p/bitly-api/wiki/ApiDocumentation">bit.ly の API</a> を使って <a href="http://davidrpoindexter.com/tutorial/bit-ly-url-shortening-with-mac-os-x-snow-leopard-services-and-applescript/">Apple Script で実装されたやつ</a>は見つかったんですけど、 API key が必要なのは面倒だし Apple Script はいやなので goo.gl を利用するサービスを shell と ruby で書いてみました。<br /><br /><script src="https://gist.github.com/927683.js?file=gistfile1.sh"></script><br /><br />このサービスは選択したテキスト(URL)を短縮して置換します。元のURLは念のためにクリップボードに保存します。<br />テキストを置換するので、編集可能なテキストしかダメなので、逆に短縮 URL をクリップボードに保存したい人は改造してください。<br /><br />Automator で作ったサービスは裏で "/System/Library/CoreServices/Automator Runnder.app" を起動して実行するんですけど、コイツの起動が遅いのでメニューバーに常駐する app がサービスを提供する感じにしたほうが速くなると思うのでそのうちに...。<br /><br />goo.gl の API は ApiKey 無しではあんまり頻繁に実行するとダメかもしれないので、ヘビーに使う人は goo.gl API の詳細: <a href="http://code.google.com/intl/ja/apis/urlshortener/v1/getting_started.html">Getting Started - Google URL Shortener API - Google Code</a> を見て自分の ApiKey を設定してみたりしてください。<br /><br />ちなみにこの記事のコード部分には <a href="http://gist.github.com">gist</a> を使ってるんですけど、gist への投稿もサービスでできたら(たぶん使わないけど)便利だと思いましたが、 gist を作成する API は <a href="http://develop.github.com/p/gist.html">Coming soon</a> だそうです (2011-04-19 現在)。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-40245810660587216742011-04-15T16:42:00.004+09:002011-05-24T09:42:12.750+09:00alias_method_chain for Objective-CObjective-C の runtime でも ruby のようにメソッドの入れ替えなどを動的に実行できるんですけどいろいろと面倒なので、 <a href="https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/module/aliasing.rb">alias_method_chain</a> の Objective-C 版を書いてみました。<br /><br /><script src="https://gist.github.com/921289.js"></script>hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-16180779433987298722011-03-23T22:29:00.002+09:002011-03-23T22:44:50.176+09:00Iodine-131 in tap water in tokyoついに東京の水道水にもヨウ素131が混入するようになったそうなので怖くなってリスクをざっくりと計算してみた。<br /><br /><a href="http://www.waterworks.metro.tokyo.jp/press/h22/press110323-01.html">水道水の放射能測定結果について / 第17報 / 平成23年3月23日 / 東京都水道局</a><br />金町浄水場: 2011/3/22 9時 I-131 210 Bq/kg<br /><a href="http://www.mhlw.go.jp/stf/houdou/2r9852000001558e-img/2r98520000015cfn.pdf">緊急時における食品の放射能測定マニュアル / 平成14年3月 / 厚生労働省医薬局食品保健部監視安全課</a><br />I-131(ヨウ化メチル以外の化合物) を幼児が経口摂取した場合の実効線量係数 0.000075 mSv/Bq<br /><br />ベクレルをシーベルトに換算すると<br />210Bq/kg * 0.000075mSv/Bq = 0.01575mSv/kg<br /><br /><a href="http://ja.wikipedia.org/wiki/シーベルト">シーベルト - Wikipedia</a><br />これ以上はヤバイかなという値を 100mSv とすると<br />100mSv / 0.01575mSv/kg = 6,349.2kg (およそ 6t)<br /><br />一日1L(1kg)水道水を飲んだりすると<br />6349.2kg / 365日 = 17.39年 で 100mSv に到達<br /><br />まあ、とりあえずはドキドキしながら暮らすとして、<br />今後数ヶ月にわたって改善されないと引っ越したくなりますね。<br /><br />免責条項<br />- 浄水場から蛇口までの話はわかりません。<br />- ヨウ素の半減期8日についても考慮してません。<br />- セシウム134やセシウム137についてはどうなんでしょう。<br />- 当然ですが、計算間違いの可能性、または仮定の間違いなどあるかと思うので、気になる人は検算してください。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-75783548060562489192011-03-07T22:22:00.005+09:002011-03-07T22:28:48.055+09:00use transactional_fixtures with capybara akephalos driver<div class="lang">You may turn on transactional fixtures with Capybara akephalos driver (it may work with selenium driver too) having the monkey-patch below in spec_helper.rb or somewhere else.<br /></div><div class="lang">akephalos driver を使っている場合でも以下のコードを spec_helper.rb にでも書いておくと transactional_fixtures を有効にできそうです。 (たぶん selenium などでも同様)</div><br /><div style="clear: both;" ></div><br /><pre><code><br />ActiveRecord::ConnectionAdapters::ConnectionPool.class_eval do<br /> def current_connection_id<br /> # Thread.current.object_id<br /> Thread.main.object_id<br /> end<br />end<br /></code></pre><br />かなり無茶苦茶な変更なので ActiveRecord を非同期に使うコードがあるとアウトなので要注意。<br /><br />以下は簡単な説明です。<br /><br />Capybara はデフォルトではサーバーも仮想ブラウザもテストを実行している ruby のプロセス内で同期的に処理するので ActiveRecord の connection をテストとサーバーで共有でき、 transactional_fixtures が使えます。<br /><br />しかし、 Selenium driver の場合ブラウザは本物、 Akephalos は HtmlUnit という Java の仮想ブラウザを別プロセスで実行しています。<br />そのため、テストのサーバーも実際の http リクエストを処理する必要があるので、 Capybara は thin や webrick を別スレッドで実行することにより対処しています。<br /><br />一方、 ActiveRecord の ConnectionPool は connection のレースコンデションを避けるためにスレッド毎に異なる connection を返すため、 fixtures ロードを含むテストとサーバーは同一トランザクションにはなりません。<br /><br />そこで、無理矢理に異なるスレッドでも ConnectionPool が同じ connection を返すように変更。真面目にこの問題に対応するためには、別スレッドでサーバーを起動せずにリクエストをブロックして rack-test で処理すればできそうな気も。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-20327527360896440812011-02-28T22:10:00.004+09:002011-02-28T22:22:05.965+09:00smart pointers for Core Foundation style referencesiOS や mac のアプリケーションを書くときに Objective-C を使うときでも、 Core Graphics などの C の API を使うときは CGImageRef などのリファレンスの開放とか面倒です。特に関数の途中で return したり、C++ のライブラリを使用するときの例外処理を考えるとウンザリです。メモリリークのリスクも高まるし。<br /><br /><pre><code><br />void doSomething(void) {<br /> CGImageRef image = CGImageCreate(......);<br /> <br /> // do something...<br /> <br /> if (some condition...)<br /> CGImageRelease(image);<br /> return;<br /> }<br /> <br /> try {<br /> CPlusPlusClass::aFunction()<br /> } catch (...) {<br /> CGImageRelease(image);<br /> return;<br /> }<br /> <br /> // use image...<br /> <br /> CGImageRelease(image);<br />}<br /></code></pre><br /><br />Objective-C のオブジェクトなら最初に autorelease しておけばいいんですけどね(iOS でなければガベージコレクションも使えるし)。<br /><br />そんなときは C++ のテンプレートで smart pointer 的なリファレンスのラッパーを書けば、ことあるごとに XXXXRelease(ref) しなくて済みます。<br /><script src="https://gist.github.com/847260.js"> </script><br /><br />これで、こんなふうに書けるようになります。<br /><pre><code><br />#include "AutoRef.h"<br /><br />void AutoRefRelease(CGImageRef ref) { CGImageRelease(ref); }<br /><br />void doSomething(void) {<br /> AutoRef<CGImage> image = CGImageCreate(......);<br /> <br /> // do something...<br /> <br /> if (some condition...)<br /> return;<br /> }<br /> <br /> try {<br /> CPlusPlusClass::aFunction()<br /> } catch (...) {<br /> return;<br /> }<br /> <br /> // use image...<br />}<br /></code></pre><br /><br />Objective-C のコードで C++ のコード使う場合(Objective-C++)は、拡張子を .mm に変えるを忘れずに。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-28019943032553495252011-02-14T22:41:00.009+09:002011-02-24T22:46:40.707+09:00a Lifehack for the redirection problem of lifehacker.comIf you can't understand Japanese, please go to <a href="#lifehack-for-redirection-problem-of.en">English part</a> of this post.<br /><br />2011-02-24: mac の場合 「プロキシ構成ファイル」として gist の <a href="https://gist.github.com/raw/841904/f7b1031fe21191d8ae3ca44484459c67f98fec50/gawker_redirect_workaround.pac.js">"view raw"</a> リンク の URLを指定すればOKなことに気がついた<br />2011-02-24: gizmodo もダメだったので追加<br />2011-02-24: pacファイルを gist に<br /><br />最近、僕の自宅から <a href="http://lifehacker.com/">lifehacker.com</a> にアクセスすると <a href="http://lifehacker.jp/">lifehacker.jp</a> にリダイレクトされるようになってしまっていました。<br /><br />調べてみると、みんなが見たい USサイトは <a href="http://us.lifehacker.com/">us.lifehacker.com</a> で、グローバルな lifehacker.com へのアクセスは親切なことになんらかの情報(アクセス元のIPアドレス?)をもとに各国の lifehacker にリダイレクトしているようです。<br /><br />で、何が問題かと言うと、最悪なことに<br /><a href="http://lifehacker.com/index.xml">USサイトのフィード</a>の記事、たとえば、<br /><a href="http://lifehacker.com/#!5757551/disable-or-restrict-plug+ins-in-chrome-to-prevent-malware-installs">"Disable or Restrict Plug-Ins in Chrome to Prevent Malware Installs [Security]"</a> のリンク先、<br /><a href="http://feeds.gawker.com/~r/lifehacker/full/~3/zLgSu5CwbAM/">http://feeds.gawker.com/~r/lifehacker/full/~3/zLgSu5CwbAM/</a><br />のリダイレクト先は<br /><a href="http://lifehacker.com/#!5757551/disable-or-restrict-plug+ins-in-chrome-to-prevent-malware-installs">http://lifehacker.com/#!5757551/disable-or-restrict-plug+ins-in-chrome-to-prevent-malware-installs</a><br />なので、<a href="http://lifehacker.jp/">lifehacker.jp</a> にリダイレクトされてしまって、該当の記事が読めないという具合。<br /><br />本題の、この問題を回避するライフハックは、以下の javascript コードを lifehacker.pac みたいな名前で保存して、プロキシ構成 (.pac) ファイルとして設定することによりリダイレクトを回避します (Mac OS X の場合です。 Windows とかはよくわかりませんが、たぶん同じような設定がどっかにあります。)<br /><script src="https://gist.github.com/841904.js"> </script><br /><br />最後に、こんなすばらしいライフハックを思いつくきっかけを与えてくれた lifehacker のリダイレクト仕様に感謝します。というか、早く直してください。お願いです。<br /><br />LifeHacker の運営母体? Gawker Media Tech のサポートサイトでも、<a href="http://getsatisfaction.com/gawker/topics/stop_redirecting_to_japanese_site">Stop redirecting to Japanese site!!</a> 同じような問題が放置されてしまっているようですね。<br /><br />以下、日本人以外のひと用。<br /><br /><div id="lifehack-for-redirection-problem-of.en"><br />If you are annoyed with the lifehacker redirect problem like this, <a href="http://getsatisfaction.com/gawker/topics/stop_redirecting_to_japanese_site">Stop redirecting to Japanese site!!</a>, this may be a help.<br /><br />SET FOLLOWING SNIPPET AS A PAC FILE:<br /><script src="https://gist.github.com/841904.js"> </script><br />Or just use URL to "view raw" link above as "Proxy configuration File" URL.<br /><br />If you don't have any clue about "pac file", try <a href="http://en.wikipedia.org/wiki/Proxy_auto-config">Proxy auto-config - Wikipedia</a>, or if you use mac, see <a href="http://docs.info.apple.com/article.html?path=Mac/10.5/en/8760.html">Apple's support page about pac file</a>.<br /><br />That's it.<br /></div>hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-75250919828636327092010-12-19T09:51:00.006+09:002010-12-19T10:15:57.078+09:00my first impression of using capybara + akephalos<a href="http://robots.thoughtbot.com/post/1658763359/thoughtbot-and-the-holy-grail">thoughtbot and the Holy Grail - GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS</a><br />を見て、 capybara + akephalos を試してみた。<br /><br />結論から言うと、 jquery-ujs ajax リクエストのテストができたんですけど、補足事項がいくつかあります。<br /><br />1. javascript_driver でなく default_driver を変更する必要があった<br />2. selenium でテストするときのように、サーバープロセスを起動してアクセスするので transactional_fixtures = false にしてテスト毎に DBの cleanup が必要<br /><br />具体的には<br /><pre># spec/spec_helper.rb<br />require 'akephalos'<br />#Capybara.javascript_driver = :akephalos <br />Capybara.default_driver = :akephalos<br /></pre><br /><br />あと DB の cleanup は <a href="https://github.com/bmabey/database_cleaner">database_cleanup</a>が便利でした。以下の例は transactional_fixtures を無効にして、全ての example が実行される前に一度 cleanup して、あとは example が終わると cleanup します。(truncate なので DatabaseCleaner.start はたぶん何もしないんですけど、 transaction strategy に変えたときには意味があるのでお約束です)<br /><br /><pre># spec/spec_helper.rb<br />RSpec.configure do |config|<br /> config.use_transactional_fixtures = false<br /> config.before(:suite) do<br /> #DatabaseCleaner.strategy = :transaction<br /> DatabaseCleaner.strategy = :truncation<br /> DatabaseCleaner.clean_with(:truncation)<br /> end<br /><br /> config.before(:each) do<br /> DatabaseCleaner.start<br /> end<br /><br /> config.after(:each) do<br /> DatabaseCleaner.clean<br /> end<br />end<br /></pre><br /><br />元記事のコメントには「selenium より遅い」という意見があります。たしかに最初の akephalos サーバーの起動には時間かかるので、rspec コマンドで単体の example もしくは example group を実行しているときにはオーバーヘッドが大きいですね。しかし、 rake spec などで全部実行するときには akephalos サーバーの起動は一度で済むので、リクエスト自体は意外とサクサクと動いて僕の selenium のツライ経験からすると全然いいですね。<br /><br />その他の注意事項としては、<br />1. 現状の akephalos (0.2.4) では capybara 0.4.0 に対応できてないので 0.3.9 を使うのですが、 <pre>within "#item_1"</pre> はダメで、 <pre>within :css, "#item_1"</pre> のように書く必要あり<br />2. webrat -> capybara 移行に際して、 capybara は rails の integration test のしくみを使ってないので、<pre>get "/"</pre> や <pre>response.should contain("hoge")</pre> が使えないので各、 <pre>visit "/"</pre>, <pre>page.should have_content("hoge")</pre> などに書き換えが必要hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-35420622908673514372010-09-23T23:20:00.005+09:002010-09-28T10:47:03.422+09:00Yet Another Offline Google Maps for iOS<a href="http://www.moongift.jp/2010/09/android-map/">Android Mapというプロジェクトの紹介記事</a>から知ったのですが、 <a href="http://mobac.dnsalias.org/">Mobile Atlas Creator</a> という Google Maps などのソースからオフラインで利用できる地図データを作成するツールがあります。<br /><br />作成した地図を iPod Touch から利用できると便利なので探してみると、 <a href="http://www.galileo-app.com/">Galileo Offline Maps</a> というのがありました。この app 本体は無料で CloudMade と OpenStreetMap のデータが利用できます。これらの Crowdsourcing マップは日本だとデータが少なくて役に立たないからなのか、否定的なレビューばかりで残念なのですが、 230円のアドインを購入すると Mobile Atlas Creator などで作成したデータをインポートできるようになります。(表示が 230 $ で焦りますが、まあ、アメリカンクオリティなのはよくあることですね。)<br /><br />オンライン地図のインポートの方法の詳細は Galileo Offline Maps の<a href="http://www.galileo-app.com/guide.html">Guide - How to Import Offline Maps</a> を参照してください。<br /><br />ちなみに、Google Maps のデータの利用に関してはグレーな感じがするのですが、 <a href="http://studioileaf.blog12.fc2.com/blog-entry-2.html">MapFolder</a> のように app 本体がダウンロードするわけではないので抹殺されないことを願います。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-81427366450317363092010-08-15T18:57:00.001+09:002010-08-15T18:57:55.117+09:00a way to specify a ruby with rvm for new windows of a screen session<pre>$ rvm use --default ruby-1.9.2</pre><br />の状態で<br /><pre>$ rvm use system</pre><br />で利用する ruby を切り替えても screen の window の環境は新規のシェルセッションになるので ruby-1.9.2 に戻ってしまう。<br />screen が新規 window を作成するときに利用する shell のスタートアップスクリプトが実行され初期化されてしまうので当たり前といえば当たり前。<br /><br />そこで、シェルスクリプトの source rvm の直後に以下のおまじないを書いて、<br /><pre>if [[ -n "$rvm_use" ]] ; then<br /> rvm use $rvm_use<br />fi</pre><br /><br />環境変数 rvm_use を与えて screen を起動すると、<br /><pre>rvm_use=system screen</pre><br />screen の新規 window が作成されるたびに rvm use system が実行されるようになります。<br /><br />もっといい方法があるかと思うので、知ってる人は教えてください。<br /> <a href="http://rvm.beginrescueend.com/workflow/screen/">RVM inside Screen</a> に描いてあることは、 screen の新規 window で script/rvm が読み込まれるようにするだけだったので残念。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-60464678950286621752010-07-24T23:48:00.005+09:002010-10-28T11:47:59.036+09:00Synchronizing files in GoodReader with Unison2010-10-28: 現状、iOS4 なら Dropbox から pdf を GoodReader で開くと GoodReader にコピーされるので、「あとで読む」ものを一度 GoodReader で開いておくほうがいいかもしれない<br />2010-08-05: -fastcheck true について追記<br />2010-08-19: unison コマンドのスペルミスを修正<br /><br /><a href="http://www.goodiware.com/goodreader.html">GoodReader</a> の <a href="http://www.goodiware.com/gr-man-tr-wifi-mac.html">WebDAVサーバー</a> をマウントして、 <a href="http://www.cis.upenn.edu/~bcpierce/unison/">Unison</a> という対話的双方向 rsync みたいなツールで双方向の同期をとる方法。Mac 限定で説明しますが、 Windows でも Unison 使えるはずだし、 WebDAV マウント (ネットワークドライブ?) できるはずなので応用してみてください。<br /><br />まずは unison のインストール。<br /><pre>$ sudo port install unison</pre><br /><br /><a href="http://www.goodiware.com/gr-man-tr-wifi-mac.html">GoodReader の WebDAVサーバーを起動</a>。<br /><br />unison を実行 (もちろん実行前にバックアップしてください)。<br /><pre>$ unison -perms 0o0 -fastcheck true ~/Dropbox/pdf /Volumes/iPodTouch.local</pre><br /><br />-perms 0o0 は双方向でパーミッションの同期をしないというオプション。<br /><br />-fastcheck true オプションを付けると同期するかどうかの確認が速くなります。<br /><br />unison は対話的なコマンドなので最初に実行するとすべて未知のファイルとしてどうするかいちいち聞いてくるのですが、落ち着いて対応すれば難しくないはずです。<br /><ul><br /><li>すでに双方にあるファイルが同じなら ">" (left to right) のローカルから iPhone へ (実際には転送されないと思う)</li><br /><li>.DS_Store とかは、 "N" (permanently ignore paths ending with this name)</li><br /><li>同じ内容だけど名前の違うフォルダやファイルはとりあえず skip して名前を調整してから次回の unison 実行で同期</li><br /></ul><br /><br />unison の実行が終わったら、 iPhone 側の "WiFi-transfer" を "stop" する前にマウントを先に解除したほうがいいですね。たぶん。<br /><br />以上。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-16998869768129171832010-04-20T16:00:00.001+09:002010-04-20T16:02:44.820+09:00Exclusively require and load tasks for rake with bundlerRails アプリケーションで Bundler の Gemfile を使う場合、<br /><pre>group :test do<br /> gem :rspec-rails<br />end<br /></pre><br />のように Rails.env に応じたグルーピングができます。<br /><br />rake でしか使わない gem とそのタスクをこの仕組でできないかなと思って、<a href="http://github.com/carlhuda/bundler/issues/issue/294#issue/294/comment/214430">bundler の issue トラッカー</a>でヒントを貰ってなんとかできました。<br /><br />Gemfile では<br /><pre>group :tasks do<br /> gem 'ar_fixtures'<br /> gem 'yaml_waml'<br />end<br /></pre><br /><br />Rakefile では<br /><pre>Bundler.require(:tasks)<br />def load_task(task_file)<br /> load Dir[Bundler.bundle_path + "gems/*/{tasks,rails/tasks,lib/tasks}/#{task_file}.rake"].first<br />end<br />load_task "ar_fixtures"<br /></pre><br /><br />これで、<br /><pre>$ rake -T db:fixtures:dump<br />...<br />rake db:fixtures:dump # Dump data to the test/fixtures/ directory.<br /></pre>hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-85323170370279665242010-04-17T11:24:00.004+09:002010-07-30T11:09:00.030+09:00a rvm tips - install rubies as root, use them as a user2010-07-30: 現状では <a href="http://rvm.beginrescueend.com/deployment/system-wide/">Installing RVM System Wide</a> に従ったほうがいいですね。たぶん。<br /><br />rvm (Ruby Version Manager)を使う場合、ユーザーホーム以下に rubies から gems までインストールして使う方法が一般的なようですが、 rails のデプロイ先のサーバーや複数ユーザーで共有しているホストなど、それだと気持ち悪い。<br />root で ruby をインストールしてユーザーからそれ使いたいのですが、いまいち方法がよくわからなかったので試行錯誤して、とりあえず動くようになったので書いておきます。<br /><br />まずは rvm gem をインストール<br /><pre>sudo gem install rvm</pre><br />(rvm 自体はシェルスクリプトの集まりなので ruby がない状態からインストールできるようですが、やったことありません。<a href="http://rvm.beginrescueend.com/rvm/install/">Installing RVM</a> を見てください。)<br /><br />次に root に /usr/local/rvm ディレクトリを作成<br /><pre>sudo rvm-install</pre><br /><br />ユーザーの設定ファイル ~/.rvmrc に rubies と gems は /usr/local/rvm を見るように設定:<br /><pre>rvm_rubies_path=/usr/local/rvm/rubies<br />rvm_gems_path=/usr/local/rvm/gems<br /></pre><br /><br />それからユーザーの ~/.rvm ディレクトリを作成<br /><pre>rvm-install</pre><br />rvm-install の仰せの通りに source $HOME/.rvm/srcipt/rvm を設定、<br />いちどログインシェルを抜けてから、<br /><br />いよいよ欲しい ruby をインストール。 <br /><pre>rvmsudo rvm install ruby-head</pre><br />通常の sudo だと sudoers に "Defaults setenv" を書いて -E しても PATH は渡されなかったりしていろいろ面倒なんですが、 rvmsudo を使うと PATH や GEM_HOME とかのruby関連の環境変数を引き渡せるので便利です。 rvm 以外にも gem, bundler などで root 権限が必要なときも rvmsudo が使えます。<br /><br />先程 ~/.rvmrc ファイルに /usr/local/rvm を参照する設定を書きましたが、現状では ruby をインストールするごとに ~/.rvm/bin にシンボリックリンクを作成する必要があるようです。<br /><pre>(cd ~/.rvm/bin && ln -s /usr/local/rvm/bin/ruby-head ruby-head)</pre><br /><br />これで、ユーザーから通常通り<br /><pre>rvm ruby-head</pre><br />とすれば switch できるようになりました。<br /><br />もっといい方法がないか <a href="http://groups.google.com/group/rubyversionmanager/browse_thread/thread/f677ac7fcbecb99e#">rvm google group にポスト</a>したところ "it may never work" とは言われなかったので個人的にはこんな感じで使おうかと思ってます。<br /><br />(ちなみに上記は rvm 0.1.27 で試しました)hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-17644989307413112602010-01-10T00:04:00.005+09:002010-01-10T00:32:43.220+09:00MacRuby now supports non-ASCII string in regular expressionsMacRuby には僕ら日本人にとって信じがたい、日本語(というかASCII以外)を含む文字列に対して正規表現が使えないという問題がありましたが、<a href="http://www.macruby.org/trac/ticket/94#comment:6">先日、修正されたようです</a>。まだ試してませんが。<br /><br />0.4 のコードベースのときに、日本人としてなんとかしないとと思い、修正しようとして挫折しましたが、<a href="http://www.macruby.org/trac/changeset/3189">r3189 changeset</a> を見ると意外と差分が少ないですね。<br /><br />MacRuby が Mac OS X 10.7 のシステムの一部として利用できるようになれば、重たい MacRuby.framework をアプリケーションに含めずにリリースできるようになることを期待しています。<br /><br />最近、ブログ書くのが億劫になってましたが、 ソフトウェアの i18n に関心がある身としてちょっと嬉しかったので...。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-88747547237344077082009-11-08T10:16:00.005+09:002009-11-08T10:18:28.304+09:00Google's OAuth doesn't seem to support wave as a scope yet?After releasing <a href="">Unofficial Google Wave Notifier</a>, many people have claimed it may steal gogle password.<br />They are right. you should not trust me nor the app. From beginning I know the issue, I'm sorry, but I'v neglected the security concern as I hasten to release the app.<br />(A poor execuse to prove my innocence. I open <a href="http://github.com/hiroshi/Unofficial-Google-Wave-Notifier/">the source</a>. Suspicious users should review the source and build a binary from reviwed source.)<br /><br />Current version (0.4) of the app uses <a href="http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html">ClientLogin for Installed Applications</a> for authentication. In the process, apps handles passwords immediatly.<br /><br />By contrast with ClientLogin, apps which uses <a href="http://code.google.com/apis/accounts/docs/OAuthForInstalledApps.html">OAuth for Installed Application</a> handles oauth tokens instead of precisous passwords.<br /><br />It is obvious that I should choose OAuth. However I can't get it so far. At <a href="http://googlecodesamples.com/oauth_playground/">OAuth Playground</a>, I tried to get oauth_token. The paramerters I specified are:<br /><pre>scope: https://wave.google.com/wave/<br />oauth_signature_method: HMAC-SHA1<br />oauth_consumer_key: anonymous<br />consumer secret: anonymous<br /></pre>And the response is:<br /><pre>Invalid scope: https://wave.google.com/wave/<br /></pre><br /><br />By choosing other scope, I can get a oauth_toke.... I missed something? or Google doesn' support wave as a oauth scope (yet)?hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com3tag:blogger.com,1999:blog-9178620729627808446.post-3926364281548552952009-11-03T22:40:00.003+09:002009-11-03T22:50:02.841+09:00Unofficial Google Wave Notifier for mac 0.4 and the notification wave<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8cKYJKG_SCwspY9-Lhs9xcPKjRGzXS6QGDltC75FAwMda6Hv6Gm2J763Npaqr8nGR9Nxw8HoMeKSGtw97aF3QBxzJUn-V-D2Nyav_AysTBqXwfonVlGFcV512TNJmRwKJADgvYQdkZBFg/s1600-h/uogwn0_4.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 129px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8cKYJKG_SCwspY9-Lhs9xcPKjRGzXS6QGDltC75FAwMda6Hv6Gm2J763Npaqr8nGR9Nxw8HoMeKSGtw97aF3QBxzJUn-V-D2Nyav_AysTBqXwfonVlGFcV512TNJmRwKJADgvYQdkZBFg/s400/uogwn0_4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5399873937676983298" /></a><br /><br />I'v just released version 0.4 of <a href="http://blog.yakitara.com/2009/10/unofficial-google-wave-notifier-for-mac.html">Unofficail Google Wave Notifier for mac</a>.<br />Also, if you wanna be notified about new releases, join <a href="https://wave.google.com/wave/#restored:wave:googlewave.com!w%252B-BJQ5dPUC">The "unoffical google wave notifier for mac" notification wave</a>.<br /><br />CHANGELOG<br />* Open a specific wave immediately by clicking a wave in the menu<br />* Display "Checked N min ago" biside "Check Now" like "Google Notifier"hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0tag:blogger.com,1999:blog-9178620729627808446.post-42852011519571275912009-10-23T12:16:00.002+09:002009-10-23T12:19:58.689+09:00Queuing ruby background processes with Ernie and BERT-RPC僕のようにインフラ系が弱い Rails プログラマにとっては、 <a href="http://github.com/">GitHub</a> のインフラ担当? <a href="http://github.com/mojombo">Tom Preston-Werner (aka mojombo)</a> の GitHub ブログポスト <a href="http://github.com/blog/530-how-we-made-github-fast">How We Made GitHub Fast - GitHub</a> は非常に参考になります。なかでも興味を引いたのは続くポスト <a href="http://github.com/blog/531-introducing-bert-and-bert-rpc">Introducing BERT and BERT-RPC</a> で紹介されている BERT-RPC とその実装の Ernie ですね。<br /><br />過去には Rails アプリケーションのバックグラウンド処理で苦労した思い出があるので今度ツールを選ぶときは以下の課題を解決してくれるやつがほしいなと思ってました。<br />1. 重たい処理が連続してリクエストされたときに並列で実行せずに1タスクごとキューイングして実行してほしい<br />2. worker が死んでも自動で代わりを起動してほしい<br />3. 非同期も同期(終了するまでブロック)も両方OK<br /><br />1 は Ernie の -n オプションで同時実行される handler の数は制限できるので -n 1 にすれば queue になるはず。<br /><br />2 は <a href="http://bert-rpc.org/">BERT-RPC</a> は call (同期), cast (非同期), info (コールバック情報などの送付) 3つの request が定義されていて、 ernie (v0.1) では call と cast の両方をサポートしているので同期/非同期両方OK。<br /><br />3 はうろ覚えだけど Erlang でふつうにサーバーを実装すれば wroker (handler) の再起動とかはかってにやってくれるはず。実際に handler の ruby プロセスを kill してもすぐ代わりが起動するので大丈夫そうだ。<br /><br />実際に queue になるか試してみた。 erlang ernie をインストール、簡単な handler を書いて、サーバーを handler 1つで起動。<br /><pre class="brush:shell"><br />$ sudo port install erlang +ssl # 時間かかります<br />...<br />$ sudo gem install ernie -s http://gemcutter.org<br /><br />$ cat > sleep.rb<br />require 'rubygems'<br />require 'ernie'<br />mod(:sleep) do<br /> fun(:wait) do |idx, sec|<br /> sleep sec<br /> print "#{idx}: awake from #{sec} sec.\r\n"<br /> end<br />end<br />^d<br /><br />$ ernie -p 9999 -n 1 -h sleep.rb<br />erl -boot start_sasl -detached +Bc +K true -smp enable -pz /Library/Ruby/Gems/1.8/gems/ernie-1.0.0/bin/../ebin \<br /> -ernie_server_app port 9999 -ernie_server_app handler '"sleep.rb"' -ernie_server_app number 10 -ernie_server_app log_level 2 -run ernie_server_app boot<br />...<br /></pre><br />別 shell の irb で 2秒スリープ指定 で 10回 cast。<br /><pre class="brush:shell"><br />$ irb -r bertrpc<br />>> svc = BERTRPC::Service.new('localhost', 9999)<br />=> #<BERTRPC::Service:0x1090988 @host="localhost", @port=9999><br />>> 10.times{|i| svc.cast.sleep.wait(i, 2) }<br />=> 10<br /></pre><br />$ ernie を実行した erlang shell では<br /><pre class="brush:shell"><br />0: awake from 2 sec.<br />1: awake from 2 sec.<br />2: awake from 2 sec.<br />3: awake from 2 sec.<br />4: awake from 2 sec.<br />5: awake from 2 sec.<br />6: awake from 2 sec.<br />7: awake from 2 sec.<br />8: awake from 2 sec.<br />9: awake from 2 sec.<br /></pre><br />実際に見てると2秒ごとに出力されていたので、ちゃんと queuing されてますね。hiroshihttp://www.blogger.com/profile/02969752674401335284noreply@blogger.com0