gemでインストールを行おうとしたときに no such file to load — mkmf (LoadError)

gemでインストールをしようとしたときに以下の様なエラーが出ることがあった。

$ sudo gem install mongo_mapper
Building native extensions. This could take a while...
ERROR: Error installing mongo_mapper:
ERROR: Failed to build gem native extension.

/usr/bin/ruby1.8 extconf.rb
extconf.rb:36:in `require': no such file to load -- mkmf (LoadError)
from extconf.rb:36

で、これの原因はネイティブの拡張モジュールをコンパイルする際に必要なヘッダファイルが無いということらしいので開発用のパッケージをインストールしてあげればよい。

$ sudo apt-get install ruby1.8-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
ruby1.8-dev
0 upgraded, 1 newly installed, 0 to remove and 127 not upgraded.
Need to get 577kB of archives.
After this operation, 1,634kB of additional disk space will be used.
Get:1 http://jp.archive.ubuntu.com/ubuntu/ lucid/main ruby1.8-dev 1.8.7.249-2 [577kB]
Fetched 577kB in 0s (1,013kB/s)
Selecting previously deselected package ruby1.8-dev.
(Reading database ... 70807 files and directories currently installed.)
Unpacking ruby1.8-dev (from .../ruby1.8-dev_1.8.7.249-2_i386.deb) ...
Setting up ruby1.8-dev (1.8.7.249-2) ...

これでヘッダファイルが導入されるので再度gemでインストールをすれば先のエラーは回避される様になる。

全文検索エンジンgroongaを使ってみる(1) – インストール

休暇中に何らかの全文検索エンジンを入れて触ってみようと決めていたのでGroongaを入れてみた。

特徴

Groongaの特徴は以下の様なところがある。

  • 操作は複数のプロトコルが利用可能
    • 独自プロトコル or HTTP or memcached binaryプロトコル
    • HTTPの場合, GETリクエストで各種クエリを投げる形。結果はJSONで得られる。
  • データ更新が高速
    • 前身のSennaMySQLMyISAMに依存していたので更新時にテーブル全体にロックがかかってボトルネックになっていたのを独自ストレージを実装したので問題が解消
  • 集計系のクエリ処理が高速
    • ドリルダウン(検索結果をグループ分けする様な処理)を高速に行うことができる
  • 管理ツール利用可能
    • phpMyAdminの様なツールが標準で付いている (HTTPを利用する設定でGroongaサーバを起動させた場合)
  • サジェスト機能
    • 渡された検索クエリを元におすすめのクエリーをユーザに提案できる
      • Groongaサーバが検索クエリー入力時を含めログに回収し、それを元に提案する
  • 検索スコアの調整
    • Groongaが検索結果として返却したスコアに対して検索スコアを調整することができる。(独自のパラメータを重みとして検索結果に反映させられる)

といった具合。
簡単に触ってみたところ、検索スコアの調整が非常にしやすい印象を持ったし、HTTPで制御できるのが非常に便利といった実感を持った。

インストール

インストールは、このページを参照するとそれぞれの環境にあわせたインストール方法が紹介されているので参照しながら導入する。
Macの場合、Macports or Homebrew が選択できるので、ここではHomebrewを使ってみる。
brewコマンドですぐにインストールが可能。

% brew install groonga
Warning: It appears you have Macports or Fink installed
Software installed with other package managers causes known problems for
Homebrew. If formula fail to build uninstall Macports/Fink and reinstall any
affected formula.
==> Downloading http://packages.groonga.org/source/groonga/groonga-1.2.4.tar.gz
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/groonga/1.2.4 --with-zlib
==> make install
/usr/local/Cellar/groonga/1.2.4: 590 files, 12M, built in 7.1 minutes

インストール完了後、groongaコマンドでインストールを確認できる。

% groonga --version
groonga 1.2.4 [darwin9.8.0,i386,utf8,match-escalation-threshold=0,nfkc,mecab,zlib,kqueue]

configure options: < '--prefix=/usr/local/Cellar/groonga/1.2.4' '--with-zlib' 'CC=/usr/bin/cc' 'CFLAGS=-O3 -march=nocona -mfpmath=sse -w -pipe' 'CXX=/usr/bin/c++' 'CXXFLAGS=-O3 -march=nocona -mfpmath=sse -w -pipe'>

これでインストール完了。
もう少しいろいろ触ったのだけど、激しくお腹が痛いので今日はここまで。

homebrew導入

f:id:hideack:20110816143245p:image

Macにhomebrew入れた。
homebrewMacPortsと同じくパッケージ管理ツールでRubyで記述されている。
たまたま試したいと思っていたプログラムの配布パッケージにhomebrewが用意されていたので使ってみた。

% /usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"

但し、環境によっては以下の様な表示が出て利用するcurlコマンドのSSL証明書の問題でインストールができない場合がある。
(GithubにHTTPS接続しなければならないのだけど、手元にあるcurl用の証明書ではSSL証明できない場合)

error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

curlのオプションで -k を指定すれば、SSL証明書の確認をスキップ*1できるのだが、更にインストールのステップを踏んでいくと、その中でcurlコマンドが更に呼ばれることが生じるので、根本的に証明書の問題を解決しておく必要がある。

お手軽な解決策がQAに出ていたので、それを参考して解決した。
以下の手順で証明書をcurlに設定しておけばSSL証明書の確認時のエラーは回避される。*2

% wget --no-check-certificate https://www.digicert.com/testroot/DigiCertHighAssuranceEVRootCA.crt;
% cat /usr/share/curl/curl-ca-bundle.crt DigiCertHighAssuranceEVRootCA.crt > new-ca-bundle.crt;
% sudo mv /usr/share/curl/curl-ca-bundle.crt /usr/share/curl/curl-ca-bundle.crt.old;
% sudo mv new-ca-bundle.crt /usr/share/curl/curl-ca-bundle.crt

これでbrewのインストールが行えるはずなので、インストールを行えばbrewコマンドが利用できる様になる。
お約束的なのは、brewコマンドを単独で実行するとusageが出力されるので参照。
以下、利用例、

% brew info ruby
ruby 1.9.2-p290
http://www.ruby-lang.org/en/
Depends on: readline, libyaml
Not installed

Consider using RVM or Cinderella to manage Ruby environments:
* RVM: http://rvm.beginrescueend.com/
* Cinderella: http://www.atmos.org/cinderella/

NOTE: By default, gem installed binaries will be placed into:
/usr/local/Cellar/ruby/1.9.2-p290/bin

You may want to add this to your PATH.

http://github.com/mxcl/homebrew/commits/master/Library/Formula/ruby.rb

参照: Brew Install results in Curl SSL certificate problem on Formula with GitHub HTTPS tarball URL

*1:結果は自己責任。本来は行うべきではない。

*2:あくまでも自己責任。本来は信頼できるブラウザからルート証明書をエクスポートして設定するのが本筋か。

PHPでクローラを書く

PHPでクローラを書くときのライブラリないかな?と探したところ、sourceforgeで見つけたので使ってみた。結構、出来が良くて少し触ってみた感じ便利そうな雰囲気。

PHPCrawl
PHPCrawl is a webcrawler/webspider-library written in PHP. It supports filters, limiters, cookie-handling, robots.txt-handling and other features.
http://sourceforge.net/projects/phpcrawl/

ダウンロードして展開した際に含まれているexample.phpを見ると、それが全てだったりするのだけど、一応以下にサンプルファイルを一部抜粋して掲載。
どの様な形で実装できるかがわかると思う。

<?php
// Inculde the phpcrawl-mainclass
include("classes/phpcrawler.class.php");
// Extend the class and override the handlePageData()-method
class MyCrawler extends PHPCrawler
{
function handlePageData(&$page_data)
{
// --- ここにコンテンツがクロールされた際の挙動を実装する
// Print the URL of the actual requested page or file
echo "Page requested: ".$page_data["url"]."\n";
// Print the first line of the header the server sent (HTTP-status)
echo "Status: ".strtok($page_data["header"], "\n")."\n";
// Print the referer
echo "Referer-page: ".$page_data["referer_url"]."\n";
// Print if the content was be recieved or not
if ($page_data["received"]==true)
echo "Content received: ".$page_data["bytes_received"]." bytes";
else
echo "Content not received";
echo "\n\n";
flush();
}
}
$crawler = &new MyCrawler();
$crawler->setURL("www.yahoo.com");  // クロール対象のWebサイト
$crawler->addReceiveContentType("/text\/html/");    // クローラで取り込む対象のContentType
$crawler->addNonFollowMatch("/.(jpg|gif|png)$/ i");  // 探索除外のファイル拡張子
$crawler->setTrafficLimit(1000 * 1024);
$crawler->go();
?>

いろいろ楽しいことできそうだな。

蛇口

蛇口が恋しい一日であった。
f:id:hideack:20060705100000j:image

jquery.ui.datepicker.mobile.js を使った際の日付選択イベント抽出

行いたかったのは、jquery.ui.datepicker.mobileで作られたカレンダーの日付をタップ(クリック)された際のそのイベントを検出すること。
jQueryのlive(type, fn)を利用すればよいということがやっとわかった。
bind関数との違いはbind(type,fn)を利用した場合、動的に後付された要素に対してはイベントの割り当てが行われないが、live(type,fn)の場合は後付された要素に対してもイベントハンドラが割り当てられる。
したがって、jquery.ui.datepicker.mobileで後付されたカレンダーの要素に対してイベントハンドラの割り当て(タップ・クリック時のイベントの割り当て)を行おうと思ったらlive(type,fn)を利用しなければいけならない。

以下、サンプル。
カレンダー中の日付をタップした際に選択された日付に対応する年月日がalertで表示されるもの。

<html>
<head> 
<meta charset="utf-8"> 
<meta name="viewport" content="width=device-width, minimum-scale=1, maximum-scale=1"> 
<link rel="stylesheet"  href="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.css" /> 
<link rel="stylesheet"  href="css/jquery.ui.datepicker.mobile.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.min.js"></script> 
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js"></script> 
<script type="text/javascript" src="js/jQuery.ui.datepicker.js"></script> 
<script type="text/javascript" src="js/jquery.ui.datepicker.mobile.js"></script> 
<script type="text/javascript">
    $(".ui-datepicker-calendar").ready(function() {
        $("td").live("click", function(){
            alert($("#datepicker").val());
        });
    });
</script>
<body>
<div data-role="page" data-theme="b" id="jqm-home">
<div data-role="content">
<form action="#" method="get">
<input type="date" name="date" id="datepicker" value="" >
</form>
</div>
</div>
</body>
</html>

もっとも、datepickerのAPIイベントハンドラの操作できそうな気もするのだが…。
いろいろ探してみたが見つけられなかった。

未解決: jquery.ui.datepicker.mobile.js を使った際の日付選択イベント抽出

その後解決→jquery.ui.datepicker.mobile.js を使った際の日付選択イベント抽出

jQuery mobileとjQuery.uiのdatepickerを利用してスマートフォン向けの日付選択ダイアログを作るところまではうまくいっているのだけど、どうしても日付の選択のイベントを検出できない。

<html>
<head> 
<meta charset="utf-8"> 
<meta name="viewport" content="width=device-width, minimum-scale=1, maximum-scale=1"> 
<!-- 中略 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.min.js"></script> 
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js"></script> 
<script type="text/javascript" src="js/jQuery.ui.datepicker.js"></script> 
<script type="text/javascript" src="js/jquery.ui.datepicker.mobile.js"></script> 
<script type="text/javascript">
    $(document).ready(function() {
        $("#datepicker").datepicker({
            onSelect:function(dateText, inst){
                alert("foobar");
            }
        });
    });
</script>
<!-- 以下略 -->

表示は問題ない。あと、日付の選択状態になるのも問題無し。

f:id:hideack:20110611170848p:image

本当はカレンダーから日付を選択されたら"foobar"とダイアログ表示させたいのだけれども表示されない。
はて、何か勘違いしているかなぁ…。

i386とプログラミングと私

久しぶりにblog更新。
家の机周りの片付けなど。壮大に散らかっていた机の上を整理する。
以前引っ越しをしてから、大雑把に片付けたままの状態がずっと続いていたので、現在の様な状況*1でないと重い腰も上がらなかったりするのでいい機会だと思って朝から作業。
引っ越してきたにもかかわらず、捨てるものがたくさん出てきたのでいらないものはまとめつつ片付けた。
片付けをしているとCPUが出てきた。…えぇ、普通の人ではありえないフレーズですね。

f:id:hideack:20110610104216j:image

intel i386DX 20MHz の石である。大分、裏のピンが曲がってしまっているけど、小さい小物類をまとめた袋の中から出てきた。
自分が小学生のときに初めてしっかり触ったパソコンのPC-9801DAに搭載されていていたCPUでパソコン本体を廃棄する際に記念に引っこ抜いておいたもの。
CPU自体にファンも要らないCPUだったからすぐに手で引っこ抜けたんじゃなかったかな。
当時、パソコンで何していたかと思いだせば、

  • プログラミング
    • N88BASICとかQuickBASICでクイズゲームとかすごろくゲーム作ったり、ベーシックマガジンに掲載されていたプログラムを入力したり...。
  • ゲーム
    • 信長の野望とか大戦略、あとBio100%のゲーム
    • そういえば花王フロッピーディスクをつくっていたのだけど、その10枚入フロッピーディスクに1枚ゲームの体験版が付いていてよく遊んだ。
    • 体験版といってもかなりしっかり出来ていて「花王ダービー」という競馬ゲームとか遊んだ記憶がある。競馬よくわからないのに(苦笑)
  • 家計簿
    • 何故か親の代わりに一時期、家計簿いれていた記憶がある。「てきぱきマム」だったかな。
  • 音楽

とかかなぁ。

あと、中学校の頃にいたっては、英語を習っていた先生が産休で休む前に「子供が産まれるまで時間つぶしするときのゲームが欲しい」と言われて、フリーソフトのゲーム詰め合わせを作ってあげた記憶がある。QuickBASICで作った自作のランチャー*2付けて。
あの頃の集中力は自画自賛だけれどものすごくて、破竹の勢い*3でBASICを書いていた記憶がある。もっとも、今考えるともっと別の手段あったんじゃないかい?とも思えるけど、当時はそうやって自分自身が作ったものと他の何かが連携するというのを見て、それを使ってもらえるのが楽しかったのだろうなぁ。

こんな振り返りをしているのは、これからどうしようかと悩んでいるからで。
お前には向いてないとも上司に言われたことも過去ありながら続けてきたエンジニア稼業を続けていいものか。それとも思い切って別の職業もあるのかな。と迷いながら。

それでもやっぱり自分はこの職業を続けたいのかなぁ。それしかできないかな。
プログラム書くの嫌いじゃないからな。

*1:所謂、浪人状態

*2:まぁ、カーソルでゲームを選んでEnterクリックでそのソフトが起動する単純なものだが。

*3:当社比