ブロガーのためのソースコード管理システムをみんなで考えませんか?

id:hakobe932のエントリ「未踏ユースに採択されました」でブロガーのためのソースコード管理システムIPA未踏ユースに採択されたそうで、とても興味深いです。


どんなシステムなのか?

ブログにコードを貼付けてもいまいち使い勝手悪いよなー、と普段から気になっていたことを解決するためのシステムを提案してみました。


つまり、私が解釈するに、

「ブロガーが公開するソースコードの再利用性を高めるためのシステム」

ということ(かな?)。


こういうのは、実際のブロガー同士でアイデアを出し合い、議論するのが良いのではないかという、いわゆる集合知の新しいアウトプットとしてはどうでしょうか?(オープンソースプロジェクトみたいに)

特にはてダの場合、技術者が多いように思うので、こういうネタは議論も盛り上がりやすいように思います。


ということで、


Blogramming Project


を提案します。

id:hakobe932さんに拒否されたり、盛り上がらなければボツですが…。


議論する具体的な内容は、

1.要望(こういうのがあればいいな)
2.情報(こういうのがあるらしいよ)
3.提案(こうすればもっとよくならない?)
4.方法(これを利用すれば実現できるかも)

こういった感じでしょうか?


id:hakobe932さんが実際、どういうアイデアを持っているのか分かりませんが(できれば公開して欲しい)、僕のアイデアはこうです。


転載機能


流行りの転載問題ですw

ソースを登録・管理する管理サーバは必要で、そこから転載できるようにする。

転載はソースコードのみ(?)。編集不可(?)。

ソースコード添削をしたり、このソース使わせてもらいましたー的な転載によるブログエントリが可能。

もちろん、ソース公開者へのリンクが維持される必要がありますが。


ソースコードを登録し、利用してもらう代わりに、自分のブログへトラフィックを誘導できるというメリットがあります。

もしくは添削してもらえた場合は、勉強にもなる。これはWikipediaのようなシステムのイメージです。

もちろん、開発にダイレクトに利用もできる。これによりサービスの立ち上げスピードが格段に向上すると思います。


このアイデアのもとは、「○○を作ってみました」系ブログでよく見る「これには△△と××のライブラリを使っています。」という記述から、それを見たとき「へ〜!そんなライブラリ知らなかった!調べてみよう」という知的好奇心をくすぐってくれる体験です。


さらに、この転載機能をベースにしたアイデア


CodeRank


です。

つまり、より多く転載されているソースコードが良いコードだという前提でPageRankよろしくCodeRankを付けるのも良いかもしれません。

勉強するときは良質のソースによるコードリーディングが良いとされていますから、このCodeRankで勉強の効率が上がりそうです。

もちろん、システム構築のヒントにもなりそうです。

そして、ランキングの高いプログラマー満足感と共にモチベーションも向上するでしょう。


どうでしょう?

ブロガーの皆さんも議論してみませんか?

盛り上がって、良いシステムが出来上がれば嬉しいです。

というか僕はとても楽しみにしています

LightShop2.0 - スライドショー自動生成

Photoshopの「Web フォとギャラリー」機能とLightBox2.0を使って、スライドショーを自動生成できるようになりました。

これはLightShopのバージョンアップ版です。「2.0」はLightBox2.0の「2.0」です。

言い訳っぽいですか?でも恥ずかしいので言い訳させて下さいw



ではデモサイトをどうぞ。


こんなのがあっという間にできます。

インストール方法

以前のエントリと同じです。

参考にインストールしたスナップショットを載せておきます。


使い方

これも以前のエントリと同じです。

参考に、上のデモサイトを作ったパラメータ設定のスナップショットを載せておきます。


指定したフォルダにHTML等が生成されます。

指定したフォルダをサーバにアップロードすればスライドショーのページが出来上がり。

Webデザインが気に入らなければ自分でスタイルシートを編集して下さい。

関係リンク

rootじゃなくてもgRubyを使いたい

上級者さん、せっかちさんは簡易版をどうぞ。

gRubyとは

gRuby(ぐるびー)とはGD*1というネイティブライブラリのRuby用インタフェースRuby/GDのラッパーライブラリです。

Ruby/GDを簡単に扱えるようにしてくれている有り難いライブラリなのです。

では、これからLinux環境のもとインストール作業です。

Ruby/GDをインストールする

gRubyを使うために、根っこになるRuby/GDをコンパイルしてインストールします。

Ruby/GDを入手する

まずはRuby/GDをダウンロードしてきます。

本家はRAA - ruby-gdなのですが、なぜかソースコードがリンク切れなので、

ここ→http://raa.ruby-lang.org/cache/ruby-gd/からダウンロードしてきます。

ちなみに、ダウンロードしてきたreadme.jaというファイルに記載されている最新バージョンの入手先URLもリンク切れでした。


では解凍します。

% tar zxvf ruby-GD-0.7.4-1.tar.gz

これでruby-GD-0.7.4というディレクトリが完成です。

Ruby/GDをコンパイル

ではネイティブライブラリを作成します。

% cd ruby-GD-0.7.4
% ruby extconf.rb [options...]
% make
# make install

という風にdoc/INSTALL.jaに書いています。

今回はroot権限が無い状態でgRubyをインストールすることが目標なので、少し変更します。

% cd ruby-GD-0.7.4
% ruby extconf.rb --with-ttf --with-freetype --with-jpeg --enable-gd2_0
% make

オプションはgRubyがサポートする機能を余すとこなく利用できるようにするモノです。

これで「GD.so」というダイナミックライブラリが出来ているはずです。

Ruby/GDをインストール

doc/INSTALL.ja通りに「make install」すると「/usr/local/lib/ruby/site_ruby/1.8/」等にコピーされるのですが、

それにはroot権限が必要です。

root権限が無ければここで諦めなければならない所ですが、諦めません。


ではどうするか、

答えは簡単。ローカルにライブラリを用意すれば良いのです。

今回は「/home/adamrocker/lib/ruby」にしましょう。

このディレクトリはどこでもOKです。最後にライブラリパスを通しますので。


では、あらためてインストール。

% cp GD.so /home/adamrocker/lib/ruby


そしてRubyのライブラリパスを通します。

「~/.bashrc」とか「~/.cshrc」などのログインシェルの設定ファイルに環境変数を定義します。


「~/.bashrc」なら

export RUBYLIB=/home/adamrocker/lib/ruby


「~/.cshrc」なら

setenv RUBYLIB=/home/adamrocker/lib/ruby


設定を反映させます。

「~/.bashrc」なら

% source ~/.bashrc


「~/.cshrc」なら

% source ~/.cshrc

これでRuby/GDのインストール完了。

gRubyをインストールする

Ruby/GDのインストールが完了したところで、ようやくgRubyをインストールしましょう。

こちらは凄く簡単です。

gRubyを入手する

まずはgRubyを入手してきます。

gRuby Project


そして、解凍・展開です。

% tar zxvf gruby-0.0.1.tar.gz

これでgruby-0.0.1というディレクトリが作られます。

gRubyをインストール

README.ja.rdの通りだとこうなります。

% ruby setup.rb config
% ruby setup.rb setup
# ruby setup.rb install

またもやroot権限を要する「#」が出てきました。


しつこいようですがroot権限を持ってません。

なので、少しオプションを加えます。

% ruby setup.rb config --prefix=/home/adamrocker/lib/ruby
% ruby setup.rb setup
% ruby setup.rb install

Linuxのインストール作業ではおなじみの「--prefix」です。


インストールディレクトリを指定できますので、ローカルのライブラリディレクトリを指定しています。

これで「/home/adamrocker/lib/ruby/lib/ruby/site_ruby/1.8/grb」なんていう長ったらしいディレクトリが出来上がってます。

こんなに深くなくて良いので、とりあえずコピーしちゃいます。

% mv /home/adamrocker/lib/ruby/lib/ruby/site_ruby/1.8/grb /home/adamrocker/lib/ruby

これにてgRubyのインストール作業は終わりです。


確認のため、gRubyに付いてくる「example/font.rb」などを実行してみて下さい。

% ruby font.rb

「font.png」が出来ていれば成功です。


それではサヨナラ。

超簡易版gRubyインストール方法

コンパイル、インストールなんて説明イラネ。って人用。

Ruby/GD

入手

http://raa.ruby-lang.org/cache/ruby-gd/

コンパイル & インストール

% tar zxvf ruby-GD-0.7.4-1.tar.gz
% cd ruby-GD-0.7.4-1
% ruby extconf.rb --with-ttf --with-freetype --with-jpeg --enable-gd2_0
% make
% cp GD.so ${HOME}/lib/ruby

Rubyライブラリパス

export RUBYLIB=${HOME}/lib/ruby

or

setenv RUBYLIB=${HOME}/lib/ruby
gRuby

入手

http://gruby.sourceforge.jp/

コンパイル & インストール

% tar zxvf gruby-0.0.1.tar.gz
% cd gruby-0.0.1
% ruby setup.rb config --prefix=/home/adamrocker/lib/ruby
% ruby setup.rb setup
% ruby setup.rb install

Rubyライブラリパス

export RUBYLIB=${RUBYLIB}:${HOME}/lib/ruby/lib/ruby/site_ruby/1.8

or

setenv RUBYLIB=${RUBYLIB}:${HOME}/lib/ruby/lib/ruby/site_ruby/1.8

超簡単インストールのグラフィックライブラリ「PureImage」

GDはネイティブライブラリなので、コンパイルが必要なのでインストールに少し手間がかかります。


そもそも、Rubyは楽しいプログラミングライフを提供してくれているのに、インストールに時間を食われるのはストレスだ!

もっと気軽に使いたいね!って人がPure Rubyで画像生成ライブラリ「PureImage」を作ってくれています。

こちらはインストール作業がコピーだけというステキな仕様です。


制作者自信が公開していることですが、現状いくつか問題点があります。

  • ドキュメント不足
  • 動作が重い(ToDo: パフォーマンスチューニング)
  • フォントを自分で作る必要がある(Javaで作る)

この問題点が問題と感じない人は是非PureImageを使ってみて下さい。僕も使ってみましたが凄い簡単に使えて楽しいです。

*1:GDとはグラフィック生成ライブラリです。本家 - http://www.boutell.com/gd/

はてなのasin記法をテスト

連続して下のように書いてみる。

asin:4761263199:detail
isbn:9784839921996:detail
asin:4569657745:detail
asin:4091810330:detail

結果どうなってるかな?↓

まずは小さな世界で1番になる

まずは小さな世界で1番になる

Web API マッシュアップブック

Web API マッシュアップブック

頭がよくなる照明術 (PHP新書)

頭がよくなる照明術 (PHP新書)

鉄コン筋クリートall in one (ビッグコミックススペシャル)

鉄コン筋クリートall in one (ビッグコミックススペシャル)


次は、何かコメントを入れてみる。

asin:4761263199:detail
著者の実体験を踏まえたビジネス書。よくあるビジネス書スタイルだが、著者の経歴がすごい。短大家庭教師で月給60万。新卒で役員になる最短距離。理想の旦那を見つける契約書。どれも面白そうです。

isbn:9784839921996:detail
Amazon、Google、Yahoo!、はてな、YouTube、FlickrなどのWebAPIを利用し、実際にマッシュアップでサービスをくみ上げるHowTo本。各APIのメソッド一覧表等もあり、勉強し終わった後は辞書として使えそう。

asin:4569657745:detail
日本は照明に関して弱いらしい。もっと照明を効果的に使えばクリエイティブなれたりポジティブになれたりリラックスできたり…。人生を豊かにする方法が学べそうです。

asin:4091810330:detail
コミック「鉄コン筋クリート」3冊を1冊にした本書。ピンポンの著者。著者書き下ろしのピンナップも付いている。映画連動企画なので逃すと後が無いかも・・・

どうだろう?↓

まずは小さな世界で1番になる

まずは小さな世界で1番になる

著者の実体験を踏まえたビジネス書。よくあるビジネス書スタイルだが、著者の経歴がすごい。短大家庭教師で月給60万。新卒で役員になる最短距離。理想の旦那を見つける契約書。どれも面白そうです。

Web API マッシュアップブック

Web API マッシュアップブック

AmazonGoogleYahoo!はてなYouTubeFlickrなどのWebAPIを利用し、実際にマッシュアップでサービスをくみ上げるHowTo本。各APIのメソッド一覧表等もあり、勉強し終わった後は辞書として使えそう。

頭がよくなる照明術 (PHP新書)

頭がよくなる照明術 (PHP新書)

日本は照明に関して弱いらしい。もっと照明を効果的に使えばクリエイティブなれたりポジティブになれたりリラックスできたり…。人生を豊かにする方法が学べそうです。

鉄コン筋クリートall in one (ビッグコミックススペシャル)

鉄コン筋クリートall in one (ビッグコミックススペシャル)

コミック「鉄コン筋クリート」3冊を1冊にした本書。ピンポンの著者。著者書き下ろしのピンナップも付いている。映画連動企画なので逃すと後が無いかも・・・

はてブRSSの要素を取得するRubyプログラム

はてブはてなブックマーク)のRSSを取得して、要素を抽出するRubyプログラムを作ってみました。

はてブRSS

まずはてブRSSを構成する要素を確認します。


はてブ

  • タイトル (title)
  • リンク (link)
  • 説明 (description)


あとは各ブックマークの

  • タイトル (title)
  • リンク (link)
  • 説明 (description)
  • ブクマした時間 (date)
  • 追加したユーザ名 (creator)
  • タグ (tags)


他に色々要素がありますが、上記の要素を組み合わせると大抵出来上がるモノなので、コアとなる要素はこれぐらいでしょうか*1

データ設計

ここからコーディング。まずはデータ設計です。

はてブの情報を格納するクラスを定義します。

# Hatena Bookmark RSS Data Class
class HatebRSS
        attr_accessor :title, :link, :description, :items
        def initialize
                @title = @link = @description = nil
                @items = Array.new
        end
end

ここでitemsはブクマしたそれぞれのサイト情報を格納する配列とします。


インスタンス変数を定義するとgetterとかsetterとかのアクセスメソッドの定義が面倒ですが、

Rubyは内部的に定義してくれる「attr_***」って修飾子があって便利です。

インタプリタ実行時にこの修飾子が付けられたインスタンス変数へのアクセスメソッドが自動で定義されます(きっと…)。

getterのみの定義はattr_reader、setterのみの定義はattr_writerで両方を定義したい場合はattr_accessorです。


話がそれました。次に、その配列の要素となるブクマの情報を格納するクラスを定義します。

# Hatena Bookmark Data Class
class HatebItem
        attr_accessor :title, :link, :description, :date, :creator, :tags
        def initialize
                @title = @link = @description = @date = @creator = nil
                @tags = Array.new
        end
end

tagsが唯一複数出現する可能性があるので配列にします。

データ取得と構築

あとは、RSSを取得しHatebItemオブジェクトを構築して、それをHatebRSSのitems配列に詰め込んでいくだけです。

ここがメインの処理です。

require 'open-uri'
require 'rss/1.0'
require 'rss/dublincore'

# Open XML(RSS) and Make RSS Object
bookmark = "http://b.hatena.ne.jp/jkondo/rss" #jkondoのはてブRSS
rss = open(bookmark){ |file| RSS::Parser.parse(file.read) }

# Set Output Encoding
rss.output_encoding = "EUC-JP"

# Set HatebRSS instance field
hateb = HatebRSS.new
hateb.title = rss.channel.title
hateb.link = rss.channel.link
hateb.description = rss.channel.description

# Set HatebItem instance field
rss.items.each{ |item|
        hi = HatebItem.new
        hi.title = item.title
        hi.link = item.link
        hi.description = item.description
        hi.date = item.dc_date
        hi.creator = item.dc_creator
        item.dc_subjects.each{ |tag|
                hi.tags << tag.content
        }
        hateb.items << hi
}

open-uriでシンプルにRSSの取得。

open(bookmark){ |file| ... }


はてブはブクマのタグがdublincoreのsubject要素なので、読込むライブラリに注意します。

require 'rss/1.0'
require 'rss/dublincore'


RSSの各要素へのアクセスにはRSS Parser標準ライブラリを利用します。

RSS::Parser.parse(file.read)

デフォルトではparseの第二引数はtrueがセットされ、RSSのバリデーション(構文チェック)が実行されます。

怪しいRSSでも取得したい場合はバリデーションをfalseにすると良いです。

少しでも高速にしたい場合も役に立つのかも?(パフォーマンス比較をしていないので分かりませんが…)

RSS::Parser.parse(file.read, false)


私の作業環境に依存して、出力文字エンコードEUC-JPにしています。

rss.output_encoding = "EUC-JP"


これではてブRSSの内容を全てコントロールできます。

テスト

試しに、はてブRSSの全要素を出力してみます。

# Test output
puts hateb.title
puts hateb.link
puts hateb.description
puts "------"
hateb.items.each { |hi|
        puts hi.title
        puts hi.link
        puts hi.description
        puts hi.date
        puts hi.creator
        hi.tags.each{ |tag|
                print tag, ", "
        }
        puts "", "------"
}

jkondoのブクマRSSの結果はこうなります。

jkondoのブックマーク
http://b.hatena.ne.jp/jkondo/
jkondoのブックマーク

------
NHKスペシャル|グーグル革命の衝撃 〜あなたの人生を“検索”が変える〜
http://www.nhk.or.jp/special/onair/070121.html

2007-01-14T17:29:12+09:00
jkondo

------
The Apple iPhone - Engadget
http://www.engadget.com/2007/01/09/the-apple-iphone/

2007-01-10T04:24:38+09:00
jkondo

------
CYCLINGTIME.com : 神宮外苑でクリテリウム開催 学連70周年記念行事
http://www.cyclingtime.com/modules/ctnews/view.php?p=3784

2006-12-28T01:09:07+09:00
jkondo
これはすごい, 
------

(略)

意外とコメントもタグも付けてないブクマが多いんですね…。


ということで、今回ははてブRSSの各要素にフルアクセスするRubyプログラムを作ってみましたというエントリでした。

全プログラムを提示しておきます。

全プログラム

require 'open-uri'
require 'rss/1.0'
require 'rss/dublincore'

# Hatena Bookmark RSS Data Class
class HatebRSS
        attr_accessor :title, :link, :description, :items
        def initialize
                @title = @link = @description = nil
                @items = Array.new
        end
end

# Hatena Bookmark Data Class
class HatebItem
        attr_accessor :title, :link, :description, :date, :creator, :tags
        def initialize
                @title = @link = @description = @date = @creator = nil
                @tags = Array.new
        end
end

# Open XML(RSS) and Make RSS Object
bookmark = "http://b.hatena.ne.jp/jkondo/rss"
rss = open(bookmark){ |file| RSS::Parser.parse(file.read, false) }

# Set Output Encoding
rss.output_encoding = "EUC-JP"

hateb = HatebRSS.new
hateb.title = rss.channel.title
hateb.link = rss.channel.link
hateb.description = rss.channel.description

# Set HatebItem instance field
rss.items.each{ |item|
        hi = HatebItem.new
        hi.title = item.title
        hi.link = item.link
        hi.description = item.description
        hi.date = item.dc_date
        hi.creator = item.dc_creator
        item.dc_subjects.each{ |tag|
                hi.tags << tag.content
        }
        hateb.items << hi
}

# Test output
puts hateb.title
puts hateb.link
puts hateb.description
puts "------"
hateb.items.each { |hi|
        puts hi.title
        puts hi.link
        puts hi.description
        puts hi.date
        puts hi.creator
        hi.tags.each{ |tag|
                print tag, ", "
        }
        puts "", "------"
}

*1:ブックマーク数というのがchannel要素の中にあるんですが、RubyRSS Parserライブラリではアクセスできないようなのでペンディング

10行で書くProxyサーバ越えのRubyプログラム

Proxyサーバを経由してあるサーバにリクエストを送りたい場合、のプログラムを書いてみた。

require 'net/http'

proxy_host = "#{プロキシサーバのドメイン}"
proxy_port = "8080" #たいてい8080ポート
host = "#{接続先ドメイン}"
path = "#{アクセスしたいファイル}"

Net::HTTP.version_1_2
puts Net::HTTP.Proxy(proxy_host, proxy_port).start(host){ |http| http.get(path).body }

ちなみにProxyサーバにログイン認証が掛かっている場合はこちら↓。

require 'net/http'

proxy_host = "#{プロキシサーバのドメイン}"
proxy_port = "8080"
proxy_user = "#{ユーザ名}"
proxy_passwd = "#{パスワード}"
host = "#{接続先ドメイン}"
path = "#{アクセスしたいファイル}"

Net::HTTP.version_1_2
puts Net::HTTP.Proxy(proxy_host, proxy_port, proxy_user, proxy_passwd).start(host){ |http| http.get(path).body }


11行になっちゃうけど、上のと平均すると10行だからイイかw

ちなみにgetした内容に日本語が含まれると文字エンコードする必要があります。


(注)パスワードが平文で流れることに対する危険性を十分認識して、ご利用は自己責任で。

Amazon Web Serviceを使ってISBN-13からASINを取得するRubyプログラム

Amazon Web Servicesを使ってISBN-13からASINを取得するPerlプログラム」をRubyで実装することで勉強させていただこうと思います。

言語仕様が少々違っても、コーディング規約に学ぶ点は多いはず。

ということでAmazon Web ServicesのE-Commerce Serviceを使って、ISBN-13からASINを取得するRubyプログラムを作ってみました。

require 'rexml/document'
require 'open-uri'
require 'kconv'

aws_access_key_id = 'あなたのAccessKeyId'

# For debug
OUTPUT_ENCODING = 'EUC-JP' # 現状意味をなしていません(汗)

# Set up ISBN.
isbn = '9784798111117' #『オブジェクト指向入門 第2版 原則・コンセプト』のISBN-13

# Set up URL.
request_url = 'http://webservices.amazon.co.jp/onca/xml'
option_list = [ 
        "Service=AWSECommerceService",
        "AWSAccessKeyId=#{aws_access_key_id}",
        "Operation=ItemLookup",
        "IdType=ISBN",
        "ItemId=#{isbn}",
        "SearchIndex=Books",
        "ResponseGroup=Request,Small",
        "Version=2007-01-15"
]

# Assemble all options.
option_string = option_list.join('&')
url = "#{request_url}?#{option_string}"

# Retrieve result.
puts "ISBN: #{isbn}"
response_xml = open(url){ |e| REXML::Document.new e }

# Compose output string.
output =<<EOD
ASIN: #{response_xml.root.elements["Items/Item/ASIN"].text}
Title: #{response_xml.root.elements["Items/Item/ItemAttributes/Title"].text}
Author: #{response_xml.root.elements["Items/Item/ItemAttributes/Author"].text}
EOD

print Kconv.toeuc(output)

実行結果です。コマンドラインの都合上EUC-JPにしています。

$ruby amazon_isbn.rb
ISBN: 9784798111117
ASIN: 4798111112
Title: オブジェクト指向入門 第2版 原則・コンセプト
Author: バートランド・メイヤー

というか、PerlのOUTPUT_ENCODINGに相当するRubyの定数が調べきれませんでした…。

これが分かれば、毎回KconvEUCエンコードする必要ないんですけどね。


そして、ここまでやっておきながらトラバで404 Blog Not Foundの中の人が添削をされていました。

perl - 勝手に添削 - isbn2asin


PerlにはURIオブジェクトがあるそうです。

Rubyでもあるのかな?option_listをHashにしてみましたが、結局Stringに変換してるので本質的に上と同じ。

どちらでも結果はもちろん同じです。

option_list = { 
        "Service" => "AWSECommerceService",
        "AWSAccessKeyId" => aws_access_key_id,
        "Operation" => "ItemLookup",
        "IdType" => "ISBN",
        "ItemId" => isbn,
        "SearchIndex" => "Books",
        "ResponseGroup" => "Request,Small",
        "Version" => "2007-01-15"
}
option_string = option_list.map{|key, val| "#{key}=#{val}" }.join('&')

PerlURIみたいなのってRubyにもあるんですかね?