ヽ( ・∀・)ノくまくまー
http://blog.s21g.com/maiha
1772
Ubuntu 10.04 (lucid) でSunJDKを使う方法
<p>Ubuntu 10.04 では、JDKのデフォルトが SunJDK から OpenJDK に変更され、SunJDK はパッケージにも含まれなくなりました。
恐らく、今後の Sun によるサポートを不安視する声が多く、
将来的に安定したパッケージリリースを行うために独立する流れになったのだと思われます。</p>
<ul>
<li><a href="https://wiki.ubuntu.com/LucidLynx/ReleaseNotes/ja">[Ubuntu] Sun JavaはPartnerリポジトリに移動しました</a></li>
</ul>
<p>しかしながら、OpenJDKは若干機能的にSunJDKに遅れている事もあり、
SunJDKが使えないと困る局面があるのも事実です。
その場合、以下のpartnerパッケージを追加することで、
10.04でもSunJDKが利用できるようです。</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>deb http://arc<wbr />hive.canon<wbr />ical.com/ lucid partner
</pre><div class="blackboard-foot"><div></div></div></p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Comment"><span class="Comment">#</span> aptitude update</span>
<span class="marker"><span class="line-numbers"> 2 </span> </span><span class="Comment"><span class="Comment">#</span> aptitude search sun-java6</span>
<span class="marker"><span class="line-numbers"> 3 </span> </span>p ia32-sun-j<wbr />ava6-bin ...
<span class="marker"><span class="line-numbers"> 4 </span> </span>p sun-java6-<wbr />bin ...
<span class="marker"><span class="line-numbers"> 5 </span> </span><span class="Comment"><span class="Comment">#</span> aptitude install sun-java6-<wbr />jdk</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<p>また、OpenJDKと併用している場合は、
下記でパッケージのデフォルト設定を SunJDK にすることが可能です。</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Comment"><span class="Comment">#</span> update-alt<wbr />ernatives --config java</span>
</pre><div class="blackboard-foot"><div></div></div></p>
Thu, 27 May 2010 14:37:12 +0000
Thu, 27 May 2010 14:37:12 +0000
maiha
1766
Hashname: 大量のファイルをScalaで楽に扱う方法
<p>ext3の1ディレクトリに大量のファイルを配置すると、
ファイルアクセスが遅くなります。
一般的な回避策は、何らかのハッシュ値でディレクトリを階層的にする方法ですが、実際にやるとなると数行でできるとは言えちょっと面倒です。
そこで、これを手軽に実現できるようにライブラリに追加しました。</p>
<p>Pathnameと同じAPIですので、
最初はPathnameで使っておいて、
数が増えたらHashnameに変えるという使い方ができるので便利だと思います。
(マイグレーションも両者で一緒にloopするだけでOK)</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>import com.<span class="Entity">s21g</span>.<span class="Entity">rubyist</span>.{<span class="Variable">Pathname</span>,<span class="Variable">Hashname</span>}
<span class="marker"><span class="line-numbers"> 2 </span> </span>
<span class="marker"><span class="line-numbers"> 3 </span> </span>val path <span class="Keyword">=</span> <span class="Variable">Pathname</span>(<span class="String"><span class="String">"</span>data/users<wbr />/910.xml<span class="String">"</span></span>)
<span class="marker"><span class="line-numbers"> 4 </span> </span>val hash <span class="Keyword">=</span> <span class="Variable">Hashname</span>(<span class="String"><span class="String">"</span>data/users<wbr />/910.xml<span class="String">"</span></span>)
<span class="marker"><span class="line-numbers"> 5 </span> </span>
<span class="marker"><span class="line-numbers"> 6 </span> </span>path.<span class="Entity">path</span> <span class="Keyword">/</span><span class="Keyword">/</span> => <span class="String"><span class="String">"</span>data/users<wbr />/910.xml<span class="String">"</span></span>
<span class="marker"><span class="line-numbers"> 7 </span> </span>hash.<span class="Entity">path</span> <span class="Keyword">/</span><span class="Keyword">/</span> => <span class="String"><span class="String">"</span>data/users<wbr />/e/2/0/e20<wbr />5ee2a5de47<wbr />1a70c1fd1b<wbr />46033a75f/<wbr />910.xml<span class="String">"</span></span>
<span class="marker"><span class="line-numbers"> 8 </span> </span>
<span class="marker"><span class="line-numbers"> 9 </span> </span>hash.<span class="Entity">write</span>(<span class="String"><span class="String">"</span>Love Scala!<span class="String">"</span></span>)
<span class="marker"><span class="line-numbers"> 10 </span> </span>hash.<span class="Entity">read</span> <span class="Keyword">/</span><span class="Keyword">/</span> => <span class="String"><span class="String">"</span>Love Scala!<span class="String">"</span></span>
</pre><div class="blackboard-foot"><div></div></div></p>
<p>また、com.s21g.r<wbr />ubyistには先日の rescue の実装も入っていますので、
よかったら使ってみてください。
jar ファイルは Downloads から入手可能です。</p>
<p><strong>参考</strong></p>
<ul>
<li><a href="http://github.com/s21g/rubyist">http://git<wbr />hub.com/s2<wbr />1g/rubyist<wbr /></a></li>
<li><a href="http://blog.s21g.com/articles/1764">Ruby スタイルの後置rescueをScalaで実現する</a></li>
</ul>
Wed, 19 May 2010 03:44:21 +0000
Wed, 19 May 2010 03:44:22 +0000
maiha
1755
公開した gem を削除する方法
<p>gem push によって、
gem の公開が大変簡単になりました。
しかし、敷居の低さは油断に繋がるもので、
近い将来、誰もが一度は秘匿性のあるファイルを誤って公開してしまい、
パニックになることでしょう。</p>
<p>今回、皆さんを出し抜く形になってしまい甚だ恐縮ではございますが、
一足先に体験させて頂きましたので、
その対処法を報告致します。</p>
<h1><a id="id_01" name="id_01">手順</a></h1>
<ol>
<li>gem yank</li>
<li>support staff への報告</li>
</ol>
<h1><a id="id_02" name="id_02">1. gem yank</a></h1>
<p>gem の新機能である yank コマンドを利用すると、
指定したバージョンの gem の公開を停止することができます。
例えば、foo-0.0.1 gem の場合、以下を実行します。</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% gem yank foo -v0.0.1
</pre><div class="blackboard-foot"><div></div></div></p>
<p>この機能は rubygems1.<wbr />3.6 にはまだ含まれて居ませんので、
"Unknown command yank" と言われた場合には、
以下のコマンドで gem を最新のものにアップグレードする必要があります。(1.3.7以降で、gemcutterも0.5.1以降であれば不要なはずです)</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>gem update --system
<span class="marker"><span class="line-numbers"> 2 </span> </span>gem install gemcutter
</pre><div class="blackboard-foot"><div></div></div></p>
<h1><a id="id_03" name="id_03">2. support staff への報告</a></h1>
<p>これで、gemcutter の index からは削除され、
gem search および install の対象からは除外されたのですが、
ホームページ上からは依然としてダウンロードが可能な状態になっています。
完全に削除しない理由は、</p>
<ul>
<li>その gem に依存関係を持つ gem が存在し得る</li>
<li>重要な gem (例えば rails) が突然なくなると困る</li>
</ul>
<p>というポリシーからのようです。
でも、
「パスワードみたいに本当に致命的な場合は、
個別に判断するのでとりあえず連絡下さい」
という方針のようなので、
以下の問い合わせフォームから削除を嘆願します。</p>
<p><a href="http://help.rubygems.org/discussion/new">http://hel<wbr />p.rubygems<wbr />.org/discu<wbr />ssion/new</a></p>
<p>これは基本的に公開BTSなので、下のほうにある</p>
<p>[x] This is a private discussion<wbr />, don't let the public see </p>
<p>を忘れずにチェックして、private なメッセージにして投稿しましょう。
これで数日中には完全に削除されるはずですので、
support staff に感謝の気持ちを伝えて作業完了です。</p>
<h1><a id="id_04" name="id_04">[おまけ] unyank</a></h1>
<p>yank を取り消す(undo)機能も存在しています。</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% gem yank foo -v0.0.1 --undo
</pre><div class="blackboard-foot"><div></div></div></p>
<p>この yank / undo の一連の操作を覚えておくと、
「もしかしてセキュリティーホールがある?」
「新バージョンでエンバグしてる?」
なんて時には速攻で yank して、
「やっぱ気のせい」
という場合は undo で戻せるので、とても便利です。</p>
<h1><a id="id_05" name="id_05">参考</a></h1>
<p><a href="http://help.rubygems.org/faqs/gemcutter/removing-a-published-rubygem">Removing a published RubyGem</a></p>
Fri, 16 Apr 2010 19:06:03 +0000
Fri, 16 Apr 2010 19:06:04 +0000
maiha
1742
thor で usage の自動生成
<h2><a id="id_01" name="id_01">thor のメリット</a></h2>
<p>thor は rake に比べて、</p>
<ul>
<li>タスク定義が Ruby メソッド</li>
<li>コマンドライン引数が簡単に扱える</li>
</ul>
<p>というメリットがあり、お気に入りです。
前者はもしかすると
「いやいや task の方が DSL 風で...」
と人によるかもしれませんが、
後者が強力なのは異論がないでしょう。
例えば、Rails の db:create を例にすると、
環境を指定するのに rake では仕方なく RAILS_ENV を使っていますが、
もし thor であれば</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">class</span> <span class="Entity">Db<span class="Superclass"> <span class="Superclass"><</span> Thor</span></span>
<span class="marker"><span class="line-numbers"> 2 </span> </span> desc <span class="String"><span class="String">"</span>create ENV<span class="String">"</span></span>, <span class="String"><span class="String">"</span>Create database for specified env<span class="String">"</span></span>
<span class="marker"><span class="line-numbers"> 3 </span> </span> <span class="Keyword">def</span> <span class="Entity">create</span>(<span class="Variable">env <span class="Keyword">=</span> <span class="String"><span class="String">'</span>developmen<wbr />t<span class="String">'</span></span></span>)
<span class="marker"><span class="line-numbers"> 4 </span> </span> ...
</pre><div class="blackboard-foot"><div></div></div></p>
<p>のように、引数の処理もデフォルト値の指定も、
ruby コードそのままで非常に直感的です。</p>
<h2><a id="id_02" name="id_02">complete usage</a></h2>
<p>でも、しばらく使っていると、
上記の desc 部分(usage, descprtion<wbr />)のうち、
前者の usage がメソッド定義と被っていて少しイライラしてきます。
そこで、get_args を利用して usage を補完するように改良してみました。</p>
<p><a href="http://github.com/maiha/thor/tree/complete-usage">http://git<wbr />hub.com/ma<wbr />iha/thor/t<wbr />ree/comple<wbr />te-usage</a></p>
<p>これにより、以下のように記述できます。</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">class</span> <span class="Entity">Db<span class="Superclass"> <span class="Superclass"><</span> Thor</span></span>
<span class="marker"><span class="line-numbers"> 2 </span> </span> desc <span class="String"><span class="String">"</span>Create database for specified env<span class="String">"</span></span>
<span class="marker"><span class="line-numbers"> 3 </span> </span> <span class="Keyword">def</span> <span class="Entity">create</span>(<span class="Variable">env <span class="Keyword">=</span> <span class="String"><span class="String">'</span>developmen<wbr />t<span class="String">'</span></span></span>)
<span class="marker"><span class="line-numbers"> 4 </span> </span> ...
</pre><div class="blackboard-foot"><div></div></div></p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">%</span> thor list
<span class="marker"><span class="line-numbers"> 2 </span> </span>thor db<span class="Constant"><span class="Constant">:</span>create</span> <span class="Variable">ENV</span> <span class="Keyword">=</span> <span class="String"><span class="String">"</span>developmen<wbr />t<span class="String">"</span></span> <span class="Comment"><span class="Comment">#</span> Create database for specified env</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<p>もちろん、従来の記法も利用可能です。
ユーザを増やして本家に取り込んでもらうと思うので、
よかったら使ってみてください。
バグ報告も大歓迎です。</p>
<h2><a id="id_03" name="id_03">インストール</a></h2>
<p>で、こういう野良 github アプリはどうするんですかね?
とりあえず適当に clone して、complete-u<wbr />sage ブランチの lib で、
gems/thor-<wbr />0.13.4/lib<wbr /> とかを直接差し替えるのが一番早い、
かも?です。
あと、もちろん get_args のインストールも必要になります。</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">%</span> gem install get_args
</pre><div class="blackboard-foot"><div></div></div></p>
Sun, 28 Mar 2010 16:13:27 +0000
Sun, 28 Mar 2010 16:13:27 +0000
maiha
1734
[NoSQL] ohm-arfreaks (redis用のAR風ORM) の使い方
<p>Ohm を使っていると色々と不満な点が見えてきます</p>
<ul>
<li>@attributes<wbr /> を得る手段がない (#attributes<wbr /> が column_nam<wbr />es を返す)</li>
<li>create!, save! がない</li>
<li>first, all がない</li>
<li>...</li>
</ul>
<p>これは AR 脳というよりも、ARの洗練されたAPIと比べてしまうと、
Ohm の未成熟さが浮き彫りになってしまうためだと思います。</p>
<h2><a id="id_01" name="id_01">ohm-arfrea<wbr />ks</a></h2>
<p>そこで、ARのメソッドをOhm上で使えるようにしたラッパーを作成しました。</p>
<p><a href="http://github.com/maiha/ohm-arfreaks">http://git<wbr />hub.com/ma<wbr />iha/ohm-ar<wbr />freaks</a></p>
<h2><a id="id_02" name="id_02">インストール</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% gem install ohm-arfrea<wbr />ks
</pre><div class="blackboard-foot"><div></div></div></p>
<h2><a id="id_03" name="id_03">例</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">require</span> <span class="String"><span class="String">'</span>ohm<span class="String">'</span></span>
<span class="marker"><span class="line-numbers"> 2 </span> </span><span class="Keyword">require</span> <span class="String"><span class="String">'</span>ohm-arfrea<wbr />ks<span class="String">'</span></span> <span class="Comment"><span class="Comment">#</span> これを追加</span>
<span class="marker"><span class="line-numbers"> 3 </span> </span>
<span class="marker"><span class="line-numbers"> 4 </span> </span><span class="Keyword">class</span> <span class="Entity">Video<span class="Superclass"> <span class="Superclass"><</span> Ohm::Model<wbr /></span></span>
<span class="marker"><span class="line-numbers"> 5 </span> </span> attribute <span class="Constant"><span class="Constant">:</span>url</span>
<span class="marker"><span class="line-numbers"> 6 </span> </span> set <span class="Constant"><span class="Constant">:</span>tags</span>
<span class="marker"><span class="line-numbers"> 7 </span> </span><span class="Keyword">end</span>
<span class="marker"><span class="line-numbers"> 8 </span> </span>
<span class="marker"><span class="line-numbers"> 9 </span> </span><span class="Support">Video</span>.<span class="Entity">create!</span>(<span class="Constant"><span class="Constant">:</span>url</span>=><span class="String"><span class="String">"</span>a<span class="String">"</span></span>)
<span class="marker"><span class="line-numbers"> 10 </span> </span><span class="Support">Video</span>.<span class="Entity">first</span>.<span class="Entity">attributes<wbr /></span>
<span class="marker"><span class="line-numbers"> 11 </span> </span>=> {<span class="Constant"><span class="Constant">:</span>url</span>=><span class="String"><span class="String">"</span>a<span class="String">"</span></span>, <span class="Constant"><span class="Constant">:</span>tags</span>=>[]}
</pre><div class="blackboard-foot"><div></div></div></p>
<p>以下のメソッドが利用可能です (0.1.0 現在)</p>
<ul>
<li>self.prima<wbr />ry_key</li>
<li>self.colum<wbr />ns</li>
<li>self.colum<wbr />n_names</li>
<li>self.conte<wbr />nt_columns<wbr /></li>
<li>self.colum<wbr />ns_hash</li>
<li>self.creat<wbr />e!</li>
<li>save!</li>
<li>self.first<wbr /></li>
<li>self.last</li>
<li>self.count<wbr /></li>
<li>self.delet<wbr />e_all</li>
<li>new_record<wbr />?</li>
<li>attributes<wbr /></li>
</ul>
<p>ARと比べると使えるメソッドは少ないですが、
これだけでも随分Ohmが快適になると思います。</p>
<h2><a id="id_04" name="id_04">backup</a></h2>
<p>例えば、redis はどこに DB を作っているかわかり辛いので
時々バックアップが欲しくなるのですが、
昔懐かしのar_fixture<wbr />s plugin 相当のことは以下のコードでできるようになります。</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Support">File</span>.<span class="Entity">open</span>(<span class="String"><span class="String">"</span>videos.yml<wbr /><span class="String">"</span></span>, <span class="String"><span class="String">"</span>w+<span class="String">"</span></span>) <span class="Keyword">do </span>|<span class="Variable">f</span>|
<span class="marker"><span class="line-numbers"> 2 </span> </span> hash <span class="Keyword">=</span> <span class="Support">Video</span>.<span class="Entity">all</span>.<span class="Entity">inject</span>({}){|<span class="Variable">h</span>,<span class="Variable">v</span>| h[v.<span class="Entity">id</span>]<span class="Keyword">=</span>v.<span class="Entity">attributes<wbr /></span>;h}
<span class="marker"><span class="line-numbers"> 3 </span> </span> f.<span class="Entity">print</span> hash.<span class="Entity">to_yaml</span>
<span class="marker"><span class="line-numbers"> 4 </span> </span><span class="Keyword">end</span>
</pre><div class="blackboard-foot"><div></div></div></p>
Tue, 16 Mar 2010 19:16:14 +0000
Tue, 16 Mar 2010 19:25:25 +0000
maiha
1730
rubygems-1.3.6 を入れてしまうと rails-2.2.2 が全滅する件
<h2><a id="id_01" name="id_01">現状</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% gem --version
<span class="marker"><span class="line-numbers"> 2 </span> </span>1.3.6
<span class="marker"><span class="line-numbers"> 3 </span> </span>
<span class="marker"><span class="line-numbers"> 4 </span> </span>% ./script/c<wbr />onsole
<span class="marker"><span class="line-numbers"> 5 </span> </span>Loading developmen<wbr />t environmen<wbr />t (Rails 2.2.2)
<span class="marker"><span class="line-numbers"> 6 </span> </span>/usr/lib/r<wbr />uby/gems/1<wbr />.8/gems/ra<wbr />ils-2.2.2/<wbr />lib/rails/<wbr />gem_depend<wbr />ency.rb:22<wbr />4:<span class="Keyword">in</span> <span class="String"><span class="String">`</span>specificat<wbr />ion':NoMethodE<wbr />rror: undefined method <span class="String">`</span></span>version_re<wbr />quirements<wbr />=<span class="String"><span class="String">'</span> for #<Gem::Depen<wbr />dency:0xb7<wbr />769604></span>
</pre><div class="blackboard-foot"><div></div></div></p>
<ul>
<li>rails 側での対応はなし</li>
<li>rubygems 側は trunk で修正済</li>
<li>rubygems の新バージョンはなかなか出ず</li>
</ul>
<h2><a id="id_02" name="id_02">対策</a></h2>
<ul>
<li>rubygems の trunk から最新版をインストールする (git じゃないのがダサイ)</li>
</ul>
<h2><a id="id_03" name="id_03">インストール</a></h2>
<p>(/tmp/ あたりの適当な場所で実行)</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% svn <span class="Storage">export</span> http://rub<wbr />ygems.ruby<wbr />forge.org/<wbr />svn/trunk/<wbr /> rubygems
<span class="marker"><span class="line-numbers"> 2 </span> </span>A rubygems
<span class="marker"><span class="line-numbers"> 3 </span> </span>A rubygems/H<wbr />istory.txt<wbr />
<span class="marker"><span class="line-numbers"> 4 </span> </span>...
<span class="marker"><span class="line-numbers"> 5 </span> </span>リビジョン 2460 をエクスポートしました。
<span class="marker"><span class="line-numbers"> 6 </span> </span>
<span class="marker"><span class="line-numbers"> 7 </span> </span>% cd rubygems
<span class="marker"><span class="line-numbers"> 8 </span> </span><span class="Comment"><span class="Comment">#</span> ruby setup.rb</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<p>(setup.rb の実行でインストールされます。必要に応じてrootで)</p>
<h2><a id="id_04" name="id_04">確認</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">%</span> .<span class="Keyword">/</span>script<span class="Keyword">/</span>console
<span class="marker"><span class="line-numbers"> 2 </span> </span><span class="Variable">Loading</span> developmen<wbr />t environmen<wbr />t (<span class="Variable">Rails</span> <span class="Constant">2.2</span>.<span class="Constant">2</span>)
<span class="marker"><span class="line-numbers"> 3 </span> </span><span class="String"><span class="String">/</span></span><span class="String">usr</span><span class="String"><span class="String">/</span></span>lib<span class="Keyword">/</span>ruby<span class="Keyword">/</span>gems<span class="Keyword">/</span><span class="Constant">1.8</span><span class="Keyword">/</span>gems<span class="Keyword">/</span>rails<span class="Keyword">-</span><span class="Constant">2.2</span>.<span class="Constant">2</span><span class="Keyword">/</span>lib<span class="Keyword">/</span>rails<span class="Keyword">/</span>gem_depend<wbr />ency.<span class="Entity">rb</span>:<span class="Constant">224</span><span class="Constant"><span class="Constant">:</span>Warning</span>:...
<span class="marker"><span class="line-numbers"> 4 </span> </span><span class="String"><span class="String">/</span></span><span class="String">usr</span><span class="String"><span class="String">/</span></span>lib<span class="Keyword">/</span>ruby<span class="Keyword">/</span>gems<span class="Keyword">/</span><span class="Constant">1.8</span><span class="Keyword">/</span>gems<span class="Keyword">/</span>rails<span class="Keyword">-</span><span class="Constant">2.2</span>.<span class="Constant">2</span><span class="Keyword">/</span>lib<span class="Keyword">/</span>rails<span class="Keyword">/</span>gem_depend<wbr />ency.<span class="Entity">rb</span>:<span class="Constant">224</span><span class="Constant"><span class="Constant">:</span>Warning</span>:...
<span class="marker"><span class="line-numbers"> 5 </span> </span>...
<span class="marker"><span class="line-numbers"> 6 </span> </span><span class="Keyword">></span> <span class="Support">User</span>.<span class="Entity">count</span>
<span class="marker"><span class="line-numbers"> 7 </span> </span>=> <span class="Constant">25707</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<p>warning が一杯出るが気にしない。
rubygems 1.3.7 が出るまで、とりあえずこれでOK。</p>
Sun, 07 Mar 2010 13:34:22 +0000
Sun, 07 Mar 2010 13:39:07 +0000
maiha
1723
[NoSQL] activetokyocabinet (TokyoTyrantのORM) の使い方
<ul>
<li>ActiveReco<wbr />rd の TC/TT アダプタ</li>
<li>AR 上で動作するので全てのAPIが利用可能</li>
</ul>
<h2><a id="id_01" name="id_01">インストール</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% gem install activetoky<wbr />ocabinet
</pre><div class="blackboard-foot"><div></div></div></p>
<h2><a id="id_02" name="id_02">サーバの起動</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% ttserver -port 11114 db.tct <span class="Keyword">&</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<ul>
<li>ポート(11114)は何でもよい</li>
<li>ファイル名も何でもよい (拡張子はtct)</li>
</ul>
<h2><a id="id_03" name="id_03">セットアップ</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">require</span> <span class="String"><span class="String">'</span>active_tok<wbr />yocabinet/<wbr />tdb<span class="String">'</span></span>
<span class="marker"><span class="line-numbers"> 2 </span> </span>
<span class="marker"><span class="line-numbers"> 3 </span> </span><span class="Support">ActiveReco<wbr />rd</span>::<span class="Entity">Base</span>.<span class="Entity">establish_<wbr />connection<wbr /></span>(
<span class="marker"><span class="line-numbers"> 4 </span> </span> <span class="Constant"><span class="Constant">:</span>adapter</span> => <span class="String"><span class="String">'</span>tokyotyran<wbr />t<span class="String">'</span></span>,
<span class="marker"><span class="line-numbers"> 5 </span> </span> <span class="Constant"><span class="Constant">:</span>database</span> => {
<span class="marker"><span class="line-numbers"> 6 </span> </span> <span class="Constant"><span class="Constant">:</span>englishes</span> => {<span class="Constant"><span class="Constant">:</span>host</span> => <span class="String"><span class="String">'</span>localhost<span class="String">'</span></span>, <span class="Constant"><span class="Constant">:</span>port</span> => <span class="Constant">11114</span>},
<span class="marker"><span class="line-numbers"> 7 </span> </span> }
<span class="marker"><span class="line-numbers"> 8 </span> </span>);
</pre><div class="blackboard-foot"><div></div></div></p>
<ul>
<li>adapter 名は 'tokyotyran<wbr />t'</li>
<li>database で利用するテーブル名と参照するTTの設定を指定する</li>
<li>以下で Englishモデルを使うので "englishes" を定義している</li>
<li>複数のモデルを使うときはやっぱりTTが複数必要?</li>
</ul>
<h2><a id="id_04" name="id_04">使い方</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">class</span> <span class="Entity">English<span class="Superclass"> <span class="Superclass"><</span> ActiveReco<wbr />rd::Base</span></span>
<span class="marker"><span class="line-numbers"> 2 </span> </span> <span class="Keyword">include</span> <span class="Support">ActiveToky<wbr />oCabinet</span>::<span class="Entity">TDB</span>
<span class="marker"><span class="line-numbers"> 3 </span> </span>
<span class="marker"><span class="line-numbers"> 4 </span> </span> string <span class="Constant"><span class="Constant">:</span>word</span>
<span class="marker"><span class="line-numbers"> 5 </span> </span> int <span class="Constant"><span class="Constant">:</span>length</span>
<span class="marker"><span class="line-numbers"> 6 </span> </span>
<span class="marker"><span class="line-numbers"> 7 </span> </span> validates_<wbr />presence_o<wbr />f <span class="Constant"><span class="Constant">:</span>word</span>, <span class="Constant"><span class="Constant">:</span>length</span>
<span class="marker"><span class="line-numbers"> 8 </span> </span>
<span class="marker"><span class="line-numbers"> 9 </span> </span> <span class="Keyword">def</span> <span class="Entity">validate</span>
<span class="marker"><span class="line-numbers"> 10 </span> </span> <span class="Variable">self</span>[<span class="Constant"><span class="Constant">:</span>length</span>] <span class="Keyword">||=</span> word.<span class="Entity">to_s</span>.<span class="Entity">size</span>
<span class="marker"><span class="line-numbers"> 11 </span> </span> <span class="Keyword">end</span>
<span class="marker"><span class="line-numbers"> 12 </span> </span><span class="Keyword">end</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<ul>
<li>ARなので validate でも何でも思い通り</li>
<li>カラム定義は string, int, float (date/datet<wbr />imeはない?)</li>
</ul>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Comment"><span class="Comment">#</span> /usr/share<wbr />/dict/word<wbr />s を流し込み</span>
<span class="marker"><span class="line-numbers"> 2 </span> </span>buf <span class="Keyword">=</span> <span class="Support">File</span>.<span class="Entity">read</span>(<span class="String"><span class="String">"</span>/usr/share<wbr />/dict/word<wbr />s<span class="String">"</span></span>)
<span class="marker"><span class="line-numbers"> 3 </span> </span>buf.<span class="Entity">scan</span>(<span class="String"><span class="String">/</span></span><span class="String">^<span class="String"><span class="String">(</span><span class="String"><span class="String">[</span>a-z<span class="String">]</span></span>+<span class="String">)</span></span>$</span><span class="String"><span class="String">/</span></span>) {
<span class="marker"><span class="line-numbers"> 4 </span> </span> <span class="Support">English</span>.<span class="Entity">create!</span>(<span class="Constant"><span class="Constant">:</span>word</span>=><span class="Variable"><span class="Variable">$</span>1</span>)
<span class="marker"><span class="line-numbers"> 5 </span> </span>}
<span class="marker"><span class="line-numbers"> 6 </span> </span>
<span class="marker"><span class="line-numbers"> 7 </span> </span><span class="Support">English</span>.<span class="Entity">count</span>
<span class="marker"><span class="line-numbers"> 8 </span> </span>=> <span class="Constant">64024</span>
<span class="marker"><span class="line-numbers"> 9 </span> </span>
<span class="marker"><span class="line-numbers"> 10 </span> </span><span class="Support">English</span>.<span class="Entity">all</span>(<span class="Constant"><span class="Constant">:</span>conditions<wbr /></span>=>[<span class="String"><span class="String">"</span>word regexp ? and length > ?<span class="String">"</span></span>, <span class="String"><span class="String">'</span>^mai<span class="String">'</span></span>, <span class="Constant">12</span>])
<span class="marker"><span class="line-numbers"> 11 </span> </span>[<span class="Comment"><span class="Comment">#</span><English id: 33247, word: "mainstream<wbr />ing", length: "13">,</span>
<span class="marker"><span class="line-numbers"> 12 </span> </span><span class="Comment"> <span class="Comment">#</span><English id: 33250, word: "maintainab<wbr />ility", length: "15">]</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<ul>
<li>正規表現の検索も可能</li>
</ul>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>e <span class="Keyword">=</span> <span class="Support">English</span>.<span class="Entity">first</span>
<span class="marker"><span class="line-numbers"> 2 </span> </span>e.<span class="Entity">delete</span>
<span class="marker"><span class="line-numbers"> 3 </span> </span><span class="Support">ActiveReco<wbr />rd</span>::<span class="Entity">StatementI<wbr />nvalid</span>: <span class="Variable">NoMethodEr<wbr />ror</span>: undefined method <span class="String"><span class="String">`</span>values_at' for 1:Fixnum: DELETE FROM englishes WHERE (id IN (1))</span>
<span class="marker"><span class="line-numbers"> 4 </span> </span><span class="String"> from /usr/lib/r<wbr />uby/gems/1<wbr />.8/gems/ac<wbr />tiverecord<wbr />-2.3.5/lib<wbr />/active_re<wbr />cord/conne<wbr />ction_adap<wbr />ters/abstr<wbr />act_adapte<wbr />r.rb:219:i<wbr />n <span class="String">`</span></span>log<span class="String"><span class="String">'</span></span>
</pre><div class="blackboard-foot"><div></div></div></p>
<p>あれ!?あれ?</p>
<h2><a id="id_05" name="id_05">まとめ</a></h2>
<ul>
<li>ARで稼動する上に正規表現による検索も可能</li>
<li>削除(delete, destroy)ができないのはご愛嬌</li>
</ul>
<p>で、一番驚いたのは、実装方法。
普通なら、ARの各メソッドをTT化していきそうなものだが、</p>
<ol>
<li>ARにSQLを作成させて</li>
<li>そのSQLをパーズして</li>
<li>TTに翻訳する</li>
</ol>
<p>その発想はなかった。目から鱗です。
というか、SQLのparserは実用性が高いのでまず、
それをgem化希望!激しく希望!!</p>
<h2><a id="id_06" name="id_06">参考</a></h2>
<ul>
<li>解説 <a href="http://d.hatena.ne.jp/winebarrel/20100106/p1">http://d.h<wbr />atena.ne.j<wbr />p/winebarr<wbr />el/2010010<wbr />6/p1</a></li>
</ul>
Fri, 26 Feb 2010 01:35:07 +0000
Fri, 26 Feb 2010 01:35:07 +0000
maiha
1722
[NoSQL] MiyazakiResistance (TokyoTyrantのORM) の使い方
<p>TokyoTyran<wbr />t を ActiveReco<wbr />rd 風のAPIで利用するライブラリ</p>
<h2><a id="id_01" name="id_01">インストール</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% gem install miyazakire<wbr />sistance
</pre><div class="blackboard-foot"><div></div></div></p>
<h2><a id="id_02" name="id_02">セットアップ</a></h2>
<p>適当なポートで TT を起動。(テーブルデータベースを利用するので *.tct)</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% ttserver -port 11114 services.t<wbr />ct <span class="Keyword">&</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<h2><a id="id_03" name="id_03">使用例</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">require</span> <span class="String"><span class="String">'</span>rubygems<span class="String">'</span></span>
<span class="marker"><span class="line-numbers"> 2 </span> </span><span class="Keyword">require</span> <span class="String"><span class="String">'</span>miyazakire<wbr />sistance<span class="String">'</span></span>
<span class="marker"><span class="line-numbers"> 3 </span> </span>
<span class="marker"><span class="line-numbers"> 4 </span> </span><span class="Keyword">class</span> <span class="Entity">Service<span class="Superclass"> <span class="Superclass"><</span> MiyazakiRe<wbr />sistance::<wbr />Base</span></span>
<span class="marker"><span class="line-numbers"> 5 </span> </span> set_server<wbr /> <span class="String"><span class="String">"</span>localhost<span class="String">"</span></span>, <span class="Constant">11114</span>, <span class="Constant"><span class="Constant">:</span>write</span>
<span class="marker"><span class="line-numbers"> 6 </span> </span> set_timeou<wbr />t <span class="Constant">1</span>
<span class="marker"><span class="line-numbers"> 7 </span> </span>
<span class="marker"><span class="line-numbers"> 8 </span> </span> set_column<wbr /> <span class="Constant"><span class="Constant">:</span>name</span> , <span class="Constant"><span class="Constant">:</span>string</span>
<span class="marker"><span class="line-numbers"> 9 </span> </span> set_column<wbr /> <span class="Constant"><span class="Constant">:</span>port</span> , <span class="Constant"><span class="Constant">:</span>integer</span>
<span class="marker"><span class="line-numbers"> 10 </span> </span> set_column<wbr /> <span class="Constant"><span class="Constant">:</span>proto</span>, <span class="Constant"><span class="Constant">:</span>string</span>
<span class="marker"><span class="line-numbers"> 11 </span> </span><span class="Keyword">end</span>
<span class="marker"><span class="line-numbers"> 12 </span> </span>
<span class="marker"><span class="line-numbers"> 13 </span> </span>buf <span class="Keyword">=</span> <span class="Support">File</span>.<span class="Entity">read</span>(<span class="String"><span class="String">"</span>/etc/servi<wbr />ces<span class="String">"</span></span>)
<span class="marker"><span class="line-numbers"> 14 </span> </span>buf.<span class="Entity">scan</span>(<span class="String"><span class="String">%r{</span>^<span class="String"><span class="String">(</span><span class="Constant">\w</span>+<span class="String">)</span></span><span class="Constant">\s</span>+<span class="String"><span class="String">(</span><span class="Constant">\d</span>+<span class="String">)</span></span>/<span class="String"><span class="String">(</span>udp|tcp<span class="String">)</span></span><span class="String">}</span></span>) {
<span class="marker"><span class="line-numbers"> 15 </span> </span> <span class="Support">Service</span>.<span class="Entity">create</span>(<span class="Constant"><span class="Constant">:</span>name</span>=><span class="Variable"><span class="Variable">$</span>1</span>, <span class="Constant"><span class="Constant">:</span>port</span>=><span class="Variable"><span class="Variable">$</span>2</span>, <span class="Constant"><span class="Constant">:</span>proto</span>=><span class="Variable"><span class="Variable">$</span>3</span>)
<span class="marker"><span class="line-numbers"> 16 </span> </span>}
<span class="marker"><span class="line-numbers"> 17 </span> </span>
<span class="marker"><span class="line-numbers"> 18 </span> </span><span class="Support">Service</span>.<span class="Entity">count</span>
<span class="marker"><span class="line-numbers"> 19 </span> </span>=> <span class="Constant">373</span>
<span class="marker"><span class="line-numbers"> 20 </span> </span>
<span class="marker"><span class="line-numbers"> 21 </span> </span><span class="Support">Service</span>.<span class="Entity">first</span>
<span class="marker"><span class="line-numbers"> 22 </span> </span>=> <span class="Comment"><span class="Comment">#</span><Service:..<wbr />. @id=1, @port=1, @proto="tcp", @name="tcpmux"></span>
<span class="marker"><span class="line-numbers"> 23 </span> </span>
<span class="marker"><span class="line-numbers"> 24 </span> </span><span class="Support">Service</span>.<span class="Entity">find_all_b<wbr />y_port</span>(<span class="Constant">80</span>)
<span class="marker"><span class="line-numbers"> 25 </span> </span>=> [<span class="Comment"><span class="Comment">#</span><Service:..<wbr />. @id=40, @port=80, @proto="tcp", @name="www">,</span>
<span class="marker"><span class="line-numbers"> 26 </span> </span><span class="Comment"> <span class="Comment">#</span><Service:..<wbr />. @id=41, @port=80, @proto="udp", @name="www">]</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<ul>
<li>データ型は :string, :integer, :date, :datetime</li>
<li>master/sla<wbr />ve, dual master をサポート</li>
<li>ARのdynamic finderもサポート</li>
<li>(created|updated)_(on|at) は magic column</li>
<li>TTへの保存キーは id の値 (数字の連番が自動付与)</li>
</ul>
<h2><a id="id_04" name="id_04">欠点</a></h2>
<ul>
<li>スキーマを途中で変更するとエラー (DB内は同じスキーマのデータが必要)</li>
<li>1モデル毎にTTサーバが1つ必要になる?</li>
<li>:date, :datetime を空にできない (Time.at(0) になる)</li>
<li>"set_" prefix が冗長</li>
</ul>
<p>という実装を見る限り、想定されたユースケースは、</p>
<ul>
<li>任意のドキュメントを格納</li>
</ul>
<p>ではなく、</p>
<ul>
<li>固定されたスキーマ定義によってTTをRDB的に利用</li>
</ul>
<p>のようだ。
ARもASも必要としないので、「TTを手軽に便利にCRUDしたい」
という用途にはピッタリだろう。</p>
<h2><a id="id_05" name="id_05">参考</a></h2>
<ul>
<li>github <a href="http://github.com/tsukasaoishi/miyazakiresistance">http://git<wbr />hub.com/ts<wbr />ukasaoishi<wbr />/miyazakir<wbr />esistance</a></li>
<li>解説 <a href="http://www.kaeruspoon.net/articles/706">http://www<wbr />.kaeruspoo<wbr />n.net/arti<wbr />cles/706</a></li>
</ul>
Thu, 25 Feb 2010 08:43:08 +0000
Thu, 25 Feb 2010 08:43:08 +0000
maiha
1720
[NoSQL] rufus-tokyo (TokyoCabinetのORM) の使い方
<h2><a id="id_01" name="id_01">TokyoCabin<wbr />etとは</a></h2>
<ul>
<li>高速なKVS</li>
<li>mixiの平林さんが作成</li>
<li>mixiの高負荷で運用されている性能と実績</li>
<li>永続化機能あり (memcachedに対する利点)</li>
<li>効率的、並列可、単純なAPI</li>
<li>単純なKVS(hash)だけでなく、B+木、テーブル(hashを値に取る)も利用可能</li>
<li>仕様書: <a href="http://1978th.net/tokyocabinet/spex-ja.html">Tokyo Cabinet第1版基本仕様書</a></li>
</ul>
<p>また親類が多く、用途に応じて使い分けることができる</p>
<ul>
<li>Tokyo Cabinet : KVSライブラリ</li>
<li>Tokyo Tyrant : TCのネットワーク対応版</li>
<li>Kyoto Cabinet : KVSライブラリ(TCとは別方向の実装)</li>
</ul>
<p>開発順序も同じで、TCというKVSを作って、TTはそれをネットワークに対応させたもの。</p>
<h2><a id="id_02" name="id_02">TCとKCの違い (余談)</a></h2>
<p>じゃあ、KCって何?何でまたKVSの作成に戻るの?後継なの?TCより強いの?
て気がするが、一言にすると、TCはシングルスレッドでの最速を追求した実装。
(汎用的だが若干速度面で甘さのある)既存のライブラリには一切頼らず、
TCのために最適化された部品を自作し、速度という神の一手を追求した「攻撃的な実装」。
言わば、一瞬の隙を見逃さない久保棋王の将棋。
でもそれは一人でやるには開発以上に保守が大変になってくる。
それに対して、KCは個々の部品レベルでの最善の一手の追求は少し緩めても、
マルチプロセスで性能が出るように再設計し、
既存のライブラリを使ってでも保守性を高めて、
結果的にトータルでの最速を目指した「負けない実装」。
言わば、渡辺竜王の将棋。
したがって、(まだ発展途上なせいもあって)シングルスレッドではTCの方が速いが、
将来を期待させてくれるツールになっている。
ということで、KCは暖かく見守りつつ、今はTC(TT)を使うことになる。
(以上、全て推測)</p>
<h2><a id="id_03" name="id_03">インストール</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% gem install rufus-toky<wbr />o
</pre><div class="blackboard-foot"><div></div></div></p>
<h2><a id="id_04" name="id_04">使用例 (TC)</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">require</span> <span class="String"><span class="String">'</span>rubygems<span class="String">'</span></span>
<span class="marker"><span class="line-numbers"> 2 </span> </span><span class="Keyword">require</span> <span class="String"><span class="String">'</span>rufus/toky<wbr />o<span class="String">'</span></span>
<span class="marker"><span class="line-numbers"> 3 </span> </span>
<span class="marker"><span class="line-numbers"> 4 </span> </span>t <span class="Keyword">=</span> <span class="Support">Rufus</span>::<span class="Entity">Tokyo</span>::<span class="Entity">Table</span>.<span class="Entity">new</span>(<span class="String"><span class="String">"</span>foo.tct<span class="String">"</span></span>)
<span class="marker"><span class="line-numbers"> 5 </span> </span>
<span class="marker"><span class="line-numbers"> 6 </span> </span>t[<span class="String"><span class="String">'</span>gem1<span class="String">'</span></span>] <span class="Keyword">=</span> {<span class="Constant"><span class="Constant">:</span>name</span>=><span class="String"><span class="String">'</span>sinatra<span class="String">'</span></span>, <span class="Constant"><span class="Constant">:</span>minor</span>=><span class="Constant">9</span>}
<span class="marker"><span class="line-numbers"> 7 </span> </span>t[<span class="String"><span class="String">'</span>gem2<span class="String">'</span></span>] <span class="Keyword">=</span> {<span class="Constant"><span class="Constant">:</span>name</span>=><span class="String"><span class="String">'</span>monk<span class="String">'</span></span>, <span class="Constant"><span class="Constant">:</span>minor</span>=><span class="Constant">0</span>}
<span class="marker"><span class="line-numbers"> 8 </span> </span>
<span class="marker"><span class="line-numbers"> 9 </span> </span>gems <span class="Keyword">=</span> t.<span class="Entity">query</span> { |<span class="Variable">q</span>|
<span class="marker"><span class="line-numbers"> 10 </span> </span> q.<span class="Entity">add_condit<wbr />ion</span> <span class="String"><span class="String">'</span>minor<span class="String">'</span></span>, <span class="Constant"><span class="Constant">:</span>numge</span>, <span class="String"><span class="String">'</span>1<span class="String">'</span></span>
<span class="marker"><span class="line-numbers"> 11 </span> </span>}
<span class="marker"><span class="line-numbers"> 12 </span> </span><span class="Comment"><span class="Comment">#</span> => [{"name"=>"sinatra", :pk=>"gem1", "minor"=>"9"}]</span>
<span class="marker"><span class="line-numbers"> 13 </span> </span>
<span class="marker"><span class="line-numbers"> 14 </span> </span>t.<span class="Entity">close</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<p>直接ハッシュを扱うため、ORMというよりHVM(Hash-Value<wbr /> Mapping)。
というかそもそも tokyocabin<wbr />et ライブラリを直接使うのと殆ど違いが見えない。
恐らく利点は</p>
<ul>
<li>全体的に記述が Ruby ぽい (エラー処理とか)</li>
<li>transactio<wbr />n サポート (ブロックで記述できる)</li>
</ul>
<p>あたりだろうか?</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>t.<span class="Entity">transactio<wbr />n</span> <span class="Keyword">do</span>
<span class="marker"><span class="line-numbers"> 2 </span> </span> <span class="Keyword">begin</span>
<span class="marker"><span class="line-numbers"> 3 </span> </span> t[<span class="String"><span class="String">'</span>gem1<span class="String">'</span></span>] <span class="Keyword">=</span> {<span class="Constant"><span class="Constant">:</span>name</span>=><span class="String"><span class="String">'</span>sinatra<span class="String">'</span></span>, <span class="Constant"><span class="Constant">:</span>minor</span>=><span class="Constant">9</span>, <span class="Constant"><span class="Constant">:</span>author</span>=><span class="String"><span class="String">'</span>user1<span class="String">'</span></span>}
<span class="marker"><span class="line-numbers"> 4 </span> </span> t[<span class="String"><span class="String">'</span>user1<span class="String">'</span></span>] <span class="Keyword">=</span> {<span class="Constant"><span class="Constant">:</span>name</span>=><span class="String"><span class="String">'</span>bmizerany<span class="String">'</span></span>}
<span class="marker"><span class="line-numbers"> 5 </span> </span> <span class="Keyword">rescue</span>
<span class="marker"><span class="line-numbers"> 6 </span> </span> t.<span class="Entity">abort</span>
<span class="marker"><span class="line-numbers"> 7 </span> </span> <span class="Keyword">end</span>
<span class="marker"><span class="line-numbers"> 8 </span> </span><span class="Keyword">end</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<p>うーん、なんか微妙かも。
やっぱりObjectに対してCRUDしたいよね。
とか思ってたら、作者(jmettraux)から
「oklahoma_m<wbr />ixerの方がいいよ」
とアドバイスを頂いた。ダメじゃん。
というか、tokyocabin<wbr />et が撒いた種とは言え、
関連ライブラリの名前の弾け方が凄い>oklahoma_m<wbr />ixer, miyazakire<wbr />sistance。</p>
<ul>
<li><a href="http://github.com/JEG2/oklahoma_mixer">http://git<wbr />hub.com/JE<wbr />G2/oklahom<wbr />a_mixer</a></li>
</ul>
Wed, 24 Feb 2010 17:31:31 +0000
Wed, 24 Feb 2010 17:31:31 +0000
maiha
1717
[NoSQL] Ohm (redis用のORM) の使い方
<h2><a id="id_01" name="id_01">redis とは</a></h2>
<ul>
<li>Cで書かれた超高速なKVS</li>
<li>オンメモリなので超高速 (約10万件操作/秒 @Xeon 2.5Ghz)</li>
<li>定期的に自動保存する永続化機能 (memcached に対する利点)</li>
<li>文字列以外にも集合型を扱える (TokyoCabin<wbr />et に対する利点)</li>
<li>公式 <a href="http://code.google.com/p/redis/">http://cod<wbr />e.google.c<wbr />om/p/redis<wbr />/</a></li>
<li>ベンチ <a href="http://code.google.com/p/redis/wiki/Benchmarks">http://cod<wbr />e.google.c<wbr />om/p/redis<wbr />/wiki/Benc<wbr />hmarks</a></li>
</ul>
<h2><a id="id_02" name="id_02">インストール</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>% gem install ohm
</pre><div class="blackboard-foot"><div></div></div></p>
<h2><a id="id_03" name="id_03">セットアップ</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">require</span> <span class="String"><span class="String">'</span>ohm<span class="String">'</span></span>
<span class="marker"><span class="line-numbers"> 2 </span> </span><span class="Support">Ohm</span>.<span class="Entity">connect</span>(<span class="Constant"><span class="Constant">:</span>port</span>=><span class="Constant">6379</span>)
</pre><div class="blackboard-foot"><div></div></div></p>
<h2><a id="id_04" name="id_04">モデル</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Keyword">class</span> <span class="Entity">Video<span class="Superclass"> <span class="Superclass"><</span> Ohm::Model<wbr /></span></span>
<span class="marker"><span class="line-numbers"> 2 </span> </span> attribute <span class="Constant"><span class="Constant">:</span>url</span>
<span class="marker"><span class="line-numbers"> 3 </span> </span> attribute <span class="Constant"><span class="Constant">:</span>created_at<wbr /></span>
<span class="marker"><span class="line-numbers"> 4 </span> </span> set <span class="Constant"><span class="Constant">:</span>tags</span>
<span class="marker"><span class="line-numbers"> 5 </span> </span>
<span class="marker"><span class="line-numbers"> 6 </span> </span> index <span class="Constant"><span class="Constant">:</span>url</span> <span class="Comment"><span class="Comment">#</span> 検索対象には全てindexを作成する</span>
<span class="marker"><span class="line-numbers"> 7 </span> </span> index <span class="Constant"><span class="Constant">:</span>tags</span> <span class="Comment"><span class="Comment">#</span> 検索対象には全てindexを作成する</span>
<span class="marker"><span class="line-numbers"> 8 </span> </span><span class="Keyword">end</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<ul>
<li>pkeyのidが勝手に定義される</li>
<li>redisで利用可能なvalueの型は、文字列と集合</li>
<li>Ohmでは文字列型を attribute で定義する</li>
<li>Ohmでは集合型を set で定義する</li>
<li>Ohmではさらに独自の list(順序付き集合), counter(増減のみ操作可能な数値) 型が利用可能</li>
</ul>
<h2><a id="id_05" name="id_05">使用例</a></h2>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span>video <span class="Keyword">=</span> <span class="Support">Video</span>.<span class="Entity">new</span>(<span class="Constant"><span class="Constant">:</span>url</span>=><span class="String"><span class="String">"</span>http://www<wbr />.you...<span class="String">"</span></span>, <span class="Constant"><span class="Constant">:</span>tags</span>=><span class="String"><span class="String">"</span>愛理<span class="String">"</span></span>)
<span class="marker"><span class="line-numbers"> 2 </span> </span>video.<span class="Entity">save</span>
<span class="marker"><span class="line-numbers"> 3 </span> </span>video.<span class="Entity">tags</span> <span class="Keyword"><<</span> <span class="String"><span class="String">"</span>cute<span class="String">"</span></span>
<span class="marker"><span class="line-numbers"> 4 </span> </span>
<span class="marker"><span class="line-numbers"> 5 </span> </span><span class="Support">Video</span>.<span class="Entity">find</span>(<span class="Constant"><span class="Constant">:</span>tags</span>=><span class="String"><span class="String">"</span>cute<span class="String">"</span></span>)
<span class="marker"><span class="line-numbers"> 6 </span> </span>=> <span class="Comment"><span class="Comment">#</span><Index: ["1", "2"]></span>
<span class="marker"><span class="line-numbers"> 7 </span> </span>
<span class="marker"><span class="line-numbers"> 8 </span> </span><span class="Support">Video</span>.<span class="Entity">find</span>(<span class="Constant"><span class="Constant">:</span>tags</span>=><span class="String"><span class="String">"</span>cute<span class="String">"</span></span>).<span class="Entity">last</span>.<span class="Entity">tags</span>
<span class="marker"><span class="line-numbers"> 9 </span> </span>=> <span class="Comment"><span class="Comment">#</span><Set: ["cute", "愛理"]></span>
</pre><div class="blackboard-foot"><div></div></div></p>
<h2><a id="id_06" name="id_06">低レベルAPI</a></h2>
<p>Object-Has<wbr />h ではなく、純粋に redis の KVS 用 API として利用する場合。</p>
<p><div class="blackboard-head"><div></div></div>
<pre class="blackboard"><span class="marker"><span class="line-numbers"> 1 </span> </span><span class="Support">Ohm</span>.<span class="Entity">redis</span>.<span class="Entity">get</span> <span class="String"><span class="String">"</span>Foo<span class="String">"</span></span> <span class="Comment"><span class="Comment">#</span> => nil</span>
<span class="marker"><span class="line-numbers"> 2 </span> </span><span class="Support">Ohm</span>.<span class="Entity">redis</span>.<span class="Entity">set</span> <span class="String"><span class="String">"</span>Foo<span class="String">"</span></span>, <span class="String"><span class="String">"</span>xxx<span class="String">"</span></span> <span class="Comment"><span class="Comment">#</span> => "OK"</span>
<span class="marker"><span class="line-numbers"> 3 </span> </span><span class="Support">Ohm</span>.<span class="Entity">redis</span>.<span class="Entity">get</span> <span class="String"><span class="String">"</span>Foo<span class="String">"</span></span> <span class="Comment"><span class="Comment">#</span> => "xxx"</span>
</pre><div class="blackboard-foot"><div></div></div></p>
<h3><a id="id_07" name="id_07">長所</a></h3>
<ul>
<li>redisのKVS性能が高いので単純レコードへの参照・記録は超高速</li>
<li>集合型を持つのでタグの扱いなどが凄く便利</li>
<li>スキーマレスでとっつきやすい</li>
<li>各操作がアトミックなのでロックがない</li>
</ul>
<h3><a id="id_08" name="id_08">短所(redis)</a></h3>
<ul>
<li>文字列型のみ(数値や日付を入れても範囲検索できないので実用的ではない)</li>
<li>検索機能が貧弱 (文字列の完全一致のみ)</li>
<li>データ保存が async</li>
<li>もちろんトランザクション処理もなし</li>
</ul>
<p>保存時間の間隔を設定できるとは言え、基本 async なのでクラッシュによるデータ損失の危険性が常にある。
その意味では、RDBのようなしっかりとしたデータストレージでなく、
前回の状態を(運が良ければ)そのまま再開してくれる memcached
という認識(利用)がよさそう。</p>
<h3><a id="id_09" name="id_09">短所(Ohm)</a></h3>
<ul>
<li>予約語チェックがなく、id 属性を指定すると謎の挙動でハマる</li>
<li>new record 時に集合型を参照するとエラー</li>
</ul>
<p>など使い辛い</p>
Mon, 22 Feb 2010 07:40:49 +0000
Mon, 22 Feb 2010 07:46:15 +0000
maiha