ひさびさ。で、rails 3.1.1 って

インストールしても、jruby/bin の中に rails の ショートカットを置いてくれないんだね?
terminal から rails と入れても、 jruby -S rails と入れても、インストールしてないと怒られるから悩んだな。

/etc/profile に path 書いて起動するようにしたけど、俺の bash の腕は危ういんだから、焦らせるなよwww

もしかして jruby の入れ方が悪かったのか、それとも 1.9 modeをデフォにしたのが悪かったのかな…
よく分からない。

やっと rails 2.3.5 がまあまあ分かるようになってきたかなと思ったところなのに、3.1.1 へ移行。前途多難です。

それにしても rails 、(2.3 だけど)死ぬほど難しかったな〜。


ps

tips を一つ。
root になれないと言われている ubuntu ですが、
sudo -i または sudo su - で root になれますよん。
では。

jruby で firefox を起動させ、webrickで作成したローカルページを開く

さて、jruby から出来るだけ簡単に デスクトップGUIアプリケーションめいたものを作るには、どうしたものかという話の続きです。

(swing(開発停止中) にしろ SWT にしろシンドイし、swing後継の javafx2.0 はまだよく分からない状態だし、そもそも ruby の世界の話じゃなくて java の世界の話に迷い込むようなものだし)

まあ、とにかく前回の続き。

前回、jruby から java api でデフォルト・ブラウザを起動させ 指定の webpage を開くことは出来たものの、どうもwebrick で作成したローカルページはエラーで開けない。なんでなのかな。

しょうがないので、firefox 決め打ちで起動させ、指定のwebrick で作成したローカルページを開いてみるスクリプト
(途中で system("firefox", "http://localhost:10080/index") と、システムコマンドを使っているので、Linux オンリーですねぇ。クロスプラットフォームにするには、os ごと場合分けのコードにしないと)

うーん。いまいち納得いかないが、しょうがないのかな…


動作環境
jruby1.6.0 
ubuntu10.04


require "webrick"
require "webrick/httputils"
include WEBrick

class MakeHTML

private_class_method :new

def initialize(req_query)

req_query.each{|key, value|
req_query[key] = HTMLUtils.escape(value)
}

@req_query = req_query
end

def self.show(req_query)
new(req_query).build
end

def build

if @req_query == {}
str = <<-EOF
<html>
<head><title>testpage1</title></head>
<body>
<p>あなたの名前は?</p>
<form action="/index" method="get">

<input type="type" name="username">

<button type="submit" name="name" value="submit1">ok</button>

</body>
</html>
EOF
else
str = <<-EOF
<html>
<head><title>testpage2</title></head>
<body>hello, #{@req_query["username"]} </body>
</html>
EOF
end

end
end

server = HTTPServer.new(:Port => 10080)

# URIリクエストを元に出力を動的に生成して応答
server.mount_proc("/index") do |req, res|
res.content_type = "text/html"
res.body = MakeHTML.show(req.query)

end

trap("INT"){ server.shutdown }

# このthread は server.start の直前に置く。タイミングを合わせるため。
Thread.new do
sleep 3
system("firefox", "http://localhost:10080/index") # 注 これはシステムコマンド!
end

server.start


=begin

まず
http://localhost:10080/index
が、firefox で自動的に開かれる。

名前をテキスト・フィールドに入力して ok ボタンを押すと、
新しいページが開かれ、hello,(入力した名前) が表示される。

なお、system("firefox", "http://localhost:10080/index")
というシステム・コマンドが使われている。

=end

jruby で、デフォルト・ブラウザを起動する。

GUI アプリケーションめいたものを作りたいと思ったとき、どのようにしてやりましょうか?
とりあえず、ローカルで CGI でやることにしてみようかなと。

というわけで、まず手始めに jruby で java6 のAPI を利用してデフォルト・ブラウザを起動するコードを下記のように書いてみました。


まあ、これで確かにデフォルト・ブラウザが起動して webpage が開かれるのではあるけれど…。(デフォルト・ブラウザを起動させ目的の webpage を開く事は達成)


けれども webrick との相性が悪いようで、ローカルで webrick の生成したcgiのページを開こうとするとエラーになるような。javaruby のコードがぶつかっているのかな? よく分からない。しょうがないから、次からは firefox で ローカルの webrick で作成したページを開く手法にしようかな…(これはうまくいくので)


先は長い…。まあ、ゆっくりと。


require "java"

import "java.awt.Desktop"
import "java.io.IOException"
import "java.net.URI"
import "java.net.URISyntaxException"

desktop = Desktop.getDesktop
uri_string = "http://www.google.co.jp"

begin

uri = URI.new(uri_string)
desktop.browse(uri)

rescue URISyntaxException => e
e.printStackTrace
rescue IOException => e
e.printStackTrace

end


=begin

デフォルト・ブラウザーが起動して指定の url が開かれる。
しかし、webrick で生成したローカルのcgiページとの相性は悪い?

以下は、元になった java コード。

import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class DefaultBrowserLauncher {

public static void main(String[] args) {

Desktop desktop = Desktop.getDesktop();
String uriString = "http://www.google.co.jp";
try {
URI uri = new URI(uriString);
desktop.browse(uri);
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

=end

jruby で xhtml。 bodyタグ 内に 新たなタグを設ける

さて、またしても jrubyxhtml の続きです。
今度は、xhtml の bodyタグ 内に 新たなタグを設けてみます。


(そもそも私は、こんなことをやってて一体なにをしないのかな、とふと疑問に思ったりします。一般的な html エディタ よりもっと思い通りに html や xhtml を扱えないかなと思っているのは間違いありませんが、どうも自分自身で目指しているゴールがよく分からない…。まあ、とりあえず、気にしないことにしましょう)


とにかく、xhtml の bodyタグ 内に 新たなタグを設けます。
で、結果は下のサンプルの通り。


動作をテストした環境について。
jruby も nokogiri も日本語は utf-8 の使用が前提です)

jruby1.5.6
nokogiri1.4.4.2
ubuntu10.04 (文字環境は utf-8 がデフォルト)

では。この項、たぶんまだまだ続くと思います。


$KCODE = 'UTF8'

require 'rubygems'
require 'nokogiri'

@doc = Nokogiri::HTML(<<-EOHTML, nil, 'utf-8')
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>タイトル</title>
<style type="text/css">
</style>
</head>

<body>

</body>

</html>
EOHTML

puts "■ tag body 内に tag h1 を新たに設ける"
puts "■ 変更前の xhtml の内容"
puts @doc.to_xhtml(:encoding => 'UTF-8')

h1_obj = Nokogiri::XML::Node.new "h1", @doc
h1_obj.content = "見出し1"

body_obj = @doc.xpath("//body")[0]
body_obj.add_child(h1_obj)

puts "■ 変更後の xhtml の内容。tag h1 が増えている"
puts @doc.to_xhtml(:encoding => 'UTF-8')

=begin

実行結果
■ tag body 内に tag h1 を新たに設ける
■ 変更前の xhtml の内容
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>タイトル</title>
<style type="text/css">
<![CDATA[
]]>
</style>
</head>
<body>

</body>
</html>
■ 変更後の xhtml の内容。tag h1 が増えている
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>タイトル</title>
<style type="text/css">
<![CDATA[
]]>
</style>
</head>
<body>

<h1>見出し1</h1></body>
</html>

=end

jruby で xhtml 。タイトル・タグの内容を置き換える

さて、jrubyxhtml の続きです。

ごくごく簡単なところから、というわけで、 title タグの内容の置き換えから。

あとはサンプル・コードを見てください。


動作をテストした環境について。
jruby も nokogiri も日本語は utf-8 の使用が前提です)

jruby1.5.6
nokogiri1.4.4.2
ubuntu10.04 (文字環境は utf-8 がデフォルト)



$KCODE = 'UTF8'

require 'rubygems'
require 'nokogiri'

@doc = Nokogiri::HTML(<<-EOHTML, nil, 'utf-8')
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>タイトル</title>
<style type="text/css">
</style>
</head>

<body>

</body>

</html>
EOHTML

puts "■ 変更前の xhtml 全体を出力する。"
puts @doc.to_xhtml(:encoding => 'UTF-8')

puts "■ tag title の内容を 新しいタイトル に変更する"

tag_title = @doc.xpath("//title")[0]
puts "□ 現在のタイトル; #{tag_title}"

tag_title.content = "新しいタイトル"
puts "□ 変更されたタイトル; #{tag_title}"

puts "■ 変更後の xhtml 全体を出力する。"
puts @doc.to_xhtml(:encoding => 'UTF-8')

=begin

実行結果
■ 変更前の xhtml 全体を出力する。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>タイトル</title>
<style type="text/css">
<![CDATA[
]]>
</style>
</head>
<body>

</body>
</html>
■ tag title の内容を 新しいタイトル に変更する
□ 現在のタイトル; <title>タイトル</title>
□ 変更されたタイトル; <title>新しいタイトル</title>
■ 変更後の xhtml 全体を出力する。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>新しいタイトル</title>
<style type="text/css">
<![CDATA[
]]>
</style>
</head>
<body>

</body>
</html>

=end

この項、まだまだ続く予定です。

jruby で xhtml 。文字化け対策

jruby でnokogiri を使い、xhtml を生成するには、to_xhtml メソッドを使うようです。

ところが、to_html メソッドを使用した場合は encoding で utf-8 を指定してあると文字化けしないのに、to_xhtml をそのまま使うと日本語が文字化けしてしまいます(この場合もブラウザで表示させると問題ありません)


いろいろ試して、なんとかしてみました。
puts @doc.to_xhtml(:encoding => 'UTF-8') と文字コードを指定してみたんですが。

以下に、xhtml における日本語の文字化け例とその対処法を示します。


動作をテストした環境について。
jruby も nokogiri も日本語は utf-8 の使用が前提です)
jruby1.5.6
nokogiri1.4.4.2
ubuntu10.04 (文字環境は utf-8 がデフォルト)


$KCODE = 'UTF8'

require 'rubygems'
require 'nokogiri'

@doc = Nokogiri::HTML(<<-EOHTML, nil, 'utf-8')
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>タイトル</title>
<style type="text/css">
</style>
</head>

<body>

</body>

</html>
EOHTML

puts "■ html では文字化けしないのに、xhtml では文字化けしてしまう例と、その対策。"

puts "■ to_html で全体を出力する。tag_title の部分、文字化け していない"
puts @doc.to_html

puts "■ to_xhtml で全体を出力する。tag_title の部分、文字化け してしまう"
puts @doc.to_xhtml

puts "■ もう一度、to_xhtml で全体を出力する。tag_title の部分、文字化け していない"
puts @doc.to_xhtml(:encoding => 'UTF-8')

=begin

実行結果
■ html では文字化けしないのに、xthml では文字化けしてしまう例と、その対策。
■ to_html で全体を出力する。tag_title の部分、文字化け していない
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>タイトル</title>
<style type="text/css">
</style>
</head>
<body>

</body>
</html>
■ to_xhtml で全体を出力する。tag_title の部分、文字化け してしまう
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>&#x30BF;&#x30A4;&#x30C8;&#x30EB;</title>
<style type="text/css">
<![CDATA[
]]>
</style>
</head>
<body>

</body>
</html>
■ もう一度、to_xhtml で全体を出力する。tag_title の部分、文字化け していない
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>タイトル</title>
<style type="text/css">
<![CDATA[
]]>
</style>
</head>
<body>

</body>
</html>

=end

nokogiri の項、たぶんまだまだ続きます。

jruby での nokogiri 。チュートリアルの勝手なまとめ おまけ

さて、
jruby における nokogiri のチュートリアルの勝手なまとめ、いちおう終わりましたけど、nokogiri というか xmlxhtml を含む html は奥が深いです。

チュートリアルの勝手なまとめ直しは、そのさわりを紹介したにすぎません。実のところ、私もまだ勉強中でよく分かってません。

nokogiri の細かい api については本家サイト(http://nokogiri.org/)の api 一覧でも見てもらうか、ruby のメタな機能を利用してメソッドを探るか、そうでないならソースを読むか、でしょうかね?
(英語サイトでもっと詳しい解説がどこかにあるかもしれませんが)

● 試しに Nokogiri::HTML::Document の public_method を求めてみる。


$KCODE = 'UTF8'
require 'rubygems'
require 'nokogiri'
require 'pp'

@doc = Nokogiri::HTML("<html><body><h1>Mr. Belvedere Fan Club</h1></body></html>")

puts "@doc の class を出力 : #{@doc.class}"
puts "@doc の public_methods を出力 : #{@doc.public_methods.sort.pretty_inspect}"

# 実行結果は略

私が nokogiri に興味を持ってのは、面白半分に Rails を触ってみて、Rails もそうですけど、xhtml がやたらに難しいな、と思ったからです。もっと楽に xhtml を扱えないかなと。

もちろん、HTMLエディタといったものはあります。ubuntu 上でも KompoZer などが利用できます。
http://sourceforge.jp/magazine/10/07/16/098249
http://kompozer.cssmaid.net/

しかし、それにしても制約がいろいろあって、思うにまかせません。もっと自由に簡単に xhtml を扱える方法はないものか、という考えから、nokogiri を調べることにしてみたのです。

私もそのあたりは研究中です。みなさんも分かったことがあったら、ブログでもなんででもレポートして下さい。


xhtml をいろいろ操作してみる土台的ななにか

# ○基本となる xhtml ファイル


$KCODE = 'UTF8'

require 'rubygems'
require 'nokogiri'

@doc = Nokogiri::HTML <<-EOHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>タイトル</title>
<style type="text/css">
</style>
</head>

<body>
<h1>見出し1</h1>
<p>段落1</p>
<p>段落2</p>
</body>

</html>
EOHTML

puts "■ 基本となる xhtml ファイル を出力"
puts @doc.to_html


=begin

実行結果
■ 基本となる xhtml ファイル を出力
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>タイトル</title>
<style type="text/css">
</style>
</head>
<body>
<h1>見出し1</h1>
<p>段落1</p>
<p>段落2</p>
</body>
</html>

=end


puts "■ 処理の基準となるタグの検索(search メソッドを使って)"

puts "□ html タグの検索"
puts @doc.search("html")

puts "□ head タグの検索"
puts @doc.search("head")

puts "□ body タグの検索"
puts @doc.search("body")

puts "■ xpath による検索"
tag_contents = @doc.xpath("//p")
puts '■ @doc.xpath("//p") の要素 を出力。'
tag_contents.each{|elem| puts elem}

=begin
実行結果
■ 処理の基準となるタグの検索(search メソッドを使って)
□ html タグの検索
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>タイトル</title>
<style type="text/css">
</style>
</head>
<body>
<h1>見出し1</h1>
<p>段落1</p>
<p>段落2</p>
</body>
</html>
□ head タグの検索
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>タイトル</title>
<style type="text/css">
</style>
</head>
□ body タグの検索
<body>
<h1>見出し1</h1>
<p>段落1</p>
<p>段落2</p>
</body>
■ xpath による検索
■ @doc.xpath("//p") の要素 を出力。
<p>段落1</p>
<p>段落2</p>

## ### 補足

tag_contents = @doc.xpath("//p")[0]
あるいは
tag_contents = @doc.xpath("//p")[1]
などとも指定できる。

また、次の形式もある。

css_elems = @doc.css("html head")

=end

puts '■ @doc.css("html head") の要素 を出力。'
css_elems = @doc.css("html head")
css_elems.each{|elem| puts elem}

=begin
実行結果
■ @doc.css("html head") の要素 を出力。
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>タイトル</title>
<style type="text/css">
</style>
</head>
=end


puts "■ 上記タグの子供のリストを求める。"

puts "□ htmlタグの子供を求める"
puts @doc.search("html").children

puts "□ headタグの子供を求める"
puts @doc.search("head").children

puts "□ bodyタグの子供を求める"
puts @doc.search("body").children

# 実行結果、略

○ノード(xml の要素)の移動・属性変更・ノードの新規作成・ラッピング に関しては、
先の勝手にまとめるチュートリアルに書きました。

では。