09/07/03 12:55:47
【よくあるしつもん】
Q:
いちからRubyを始める初心者向けのRuby入門書は何がありますか?
A:
プログラム作成自体の初心者なら
「たのしいRuby 第2版 Rubyではじめる気軽なプログラミング」
URLリンク(www.amazon.co.jp)
文法は理解済み(orリファレンスで乗り切る既言語習得者)の場合のRuby様式を知る必携2冊目
「初めてのRuby」
URLリンク(www.amazon.co.jp)
以下は外れが少ないとされている本です。必ず立ち読みした上で自分の目的とレベルに応じて購入してください
「Rubyレシピブック 第2版 268の技」(初心者向け)
URLリンク(www.amazon.co.jp)
「プログラミングRuby 第2版 言語編」(初心者向け)
URLリンク(www.amazon.co.jp)
「Ruby Way 第2版」(脱初心者向け)
URLリンク(www.amazon.co.jp)
「Rubyクックブック ―エキスパートのための応用レシピ集」(脱初心者向け)
URLリンク(www.amazon.co.jp)
以下の本は言語作者が書いた最新本ですがとりあえず初学者向けではありません
「プログラミング言語 Ruby」(言語として深く知りたい人向け)
URLリンク(www.amazon.co.jp)
3:デフォルトの名無しさん
09/07/03 12:56:28
Ruby 公式・非公式便利サイト2009
Ruby Home Page 【公式、お役立ち度が微妙】
URLリンク(www.ruby-lang.org)
Rubyリファレンスマニュアル 【検索機能休止中、Googleなどの併用を】
URLリンク(www.ruby-lang.org)
URLリンク(www.ruby-doc.org) 【詳しい英語版】
HTMLヘルプ版リファレンスマニュアル配布さん 【Windowsで便利、検索も無論可能】
URLリンク(elbereth-hp.hp.infoseek.co.jp)
Programming Ruby - The Pragmatic Programmer's Guide 【好評書籍の初版がネットで、ただし英語】
URLリンク(www.ruby-doc.org)
Rubyist Magazine - るびま 【ライブラリ紹介などの読み物、過去のコードレビューは一読の価値あり】
URLリンク(jp.rubyist.net)
逆引きRuby 【やりたいことから探すWiki、最近元気ないので編集者募集】
URLリンク(www.namaraii.com)
はてなキーワード > Ruby 【うっかりどっさりまとまったリンク集、説明なし】
URLリンク(d.hatena.ne.jp)
RubyForge 【○○をやりたい管理されたライブラリを探すならここ、英語】
URLリンク(www.rubyforge.org)
GitHub 【○○をやりたいコードをとにかく探すならここ、英語】
URLリンク(github.com)
日本Rubyの会 【最近はオフライン勉強会の寄り合い場と化しているので近くで勉強会があれば】
URLリンク(jp.rubyist.net)
4:デフォルトの名無しさん
09/07/03 12:57:12
関連スレ
Rubyについて Part 36
スレリンク(tech板)
アンチスレ
Rubyについて(アンチ専用) Part003
スレリンク(tech板)
Railsスレ
【Ruby】Ruby on Rails Part7
スレリンク(php板)
Windows用スレ
【ActiveScript】RubyをWindowsで使うスレ【GUI】
スレリンク(tech板)
Ruby 1.9 系列スレ
魁け! Ruby 1.9.X
スレリンク(tech板)
5:デフォルトの名無しさん
09/07/03 12:57:56
前スレ
Ruby 初心者スレッド Part 28
スレリンク(tech板)
6:デフォルトの名無しさん
09/07/03 13:57:32
instance_variable_get()
instance_variable_get()
instance_variable_defined?()
はありますが
instance_variable_delete()
はないでしょうか。
あるオブジェクトからインスタンス変数を完全に取り除く方法があれば教えてください。
7:デフォルトの名無しさん
09/07/03 14:16:18
現状ではない
8:デフォルトの名無しさん
09/07/03 14:19:45
というかそのへんに依存したコードは書くべきではないと思う
9:デフォルトの名無しさん
09/07/03 15:13:57
>>6
remove_instance_variable
ちなみに俺は>>8の意見には反対、使っても全然OK派
10:デフォルトの名無しさん
09/07/03 15:54:57
リフレクション機能を使うべき場面で使うのは全然問題ないのだが、今が使うべき場面なのかどうかは真剣に考慮しよう。
11:デフォルトの名無しさん
09/07/03 16:18:30
98パーセントくらいは使う必要ないよね
12:デフォルトの名無しさん
09/07/03 16:23:58
プログラミング言語ruby読んでクラス定義とかのフックの柔軟さを知ったときは
キモッって思った一方これ使ったら綺麗に書けそうなプログラムがあるなあとも思った
13:デフォルトの名無しさん
09/07/03 16:28:20
多くは「○○という機能を使ってみた」程度であるのは否定はしない
ふつーに書いたほうがわかりやすいし、多くの場合動作も速い
14:デフォルトの名無しさん
09/07/03 17:22:37
普通に書けるなら普通に書くのがいい
さらに特殊なケースへの対応として、
プログラマがその気になればRubyは大抵の無茶を許してくれる
15:デフォルトの名無しさん
09/07/03 17:57:24
仕事でRubyを使う場合は、どんな業務になりますか?
やはりWeb系ですか?
16:デフォルトの名無しさん
09/07/03 17:58:27
>>15
仕事でRubyを使うことはないです
強いて言うなら趣味グラマーの用途しかありません
17:デフォルトの名無しさん
09/07/03 18:14:43
>>15
サーバは自前で用意するから、という案件が2年でやっと2個
Java, PHP > 量産の壁 >> Perl >> なんかシャレにならない壁 >> Ruby on Rails > Python (激レア)
こんな感じ
「こんなソフト作ってという仕事取ってきたからじゃあRubyで作ろうぜ」というのはまずありえない
言語は伏せるけどシステム作るから買ってーという営業込みでないとお金にならない
Rubyが社内ツールとしての地位を確立してて、
とっても便利に業務進めてる会社に心当たりがこれまた2つあるが、
じゃあこの便利なRubyでシステム作って売ろうぜという話には間違ってもなってないようだ
まあ適材適所って奴だな
Rubyを使えるということを評価する会社はいい会社だと思うが、Rubyしか使えない人を雇う会社は駄目会社
18:デフォルトの名無しさん
09/07/03 18:26:58
>>16
なるほど、そうですか。残念ですね。
>>17
やっぱり、Java、PHPなんですね。
まだまだ普及というか認められていないんですね。
趣味でしこしこ勉強します。
19:デフォルトの名無しさん
09/07/03 18:28:17
>>18
認めるというか、Rubyにする必要性がないといった感じ
20:デフォルトの名無しさん
09/07/03 18:43:24
Webサービスを作って、ベンチャー起業で金稼ぐのならRubyでも行けるかもしれないが
そもそも日本でベンチャーを興すのは難しいらしいしな
21:デフォルトの名無しさん
09/07/03 18:55:04
>>19
それだと今後も期待薄ですね。
>>20
限られた人らのツールになりそう。
22:デフォルトの名無しさん
09/07/03 22:01:18
>>9
>remove_instance_variable
ありがとうございます。これってprivateメソッドだったんですね。
Object.new.methods.grep(/instance/) で探してたので、見つけられませんでした。
精進します。
23:デフォルトの名無しさん
09/07/03 22:21:11
とりあえず、rubyの遅さとメモリ量の食い方で、自分のサーバーで適当に
遊んでるくらいしか使ってないなー。
あっ、後初期設定だるいかなー
apacheにfast cgi入れてうんたらかんたらは面倒~
24:デフォルトの名無しさん
09/07/03 22:45:14
だれか
RAA - net-yjwsを持ってない?もしくは配布している所知らない?
URLリンク(raa.ruby-lang.org)
のファイル配布先であるmoonwolfのサーバが死んでるみたいで手に入らない.
インターネットアーカイブで引っこ抜けるかなと思ったけどそっちでもダメでした.
25:デフォルトの名無しさん
09/07/03 23:48:07
下にある 0.0.20060523.tar.gz のリンクはruby-lang.orgに
置かれている実tar玉で、生きているようだ。
とりあえずそれで凌げるかどうか試してみては?
26:24
09/07/04 01:06:42
>>25
そっちもブラウザでやってみたんですけどFirefoxでは
内容符号化 (Content-Encoding) に問題があります
IEとChromeではつながらず。
UnixからwgetではDLできたけど展開できませんでした
27:デフォルトの名無しさん
09/07/04 01:37:19
リンクは...tar.gzになってるけど中身はHTMLみたい
28:デフォルトの名無しさん
09/07/04 12:42:27
質問があります
$stdoutでファイルを指定し、そこに結果を入れるようにしたのですが、
できたファイルを開くと、結果の頭部分しか入っておらず、困っています
エラーはでていませんし、標準出力の場合や、リダイレクトをした場合は結果の全てがきちんと出力されています
プログラムは以下です
sv = STDOUT.dup
$stdout = File.open("ファイル名", "w")
結果を出力
$stdout = sv
わかる方いましたら教えていただけないでしょうか
OSはLinuxでRubyのバージョンは1.8.5です
29:デフォルトの名無しさん
09/07/04 12:48:04
flushしてみたら?
30:デフォルトの名無しさん
09/07/04 12:52:48
・ ファイルに出力するよモードになったときはファイルに出力
・ ファイルに出力するよモードじゃないときは標準出力に出力
・ これを $stdout への代入だけで切り替えたい
という処理をしたいと推測
いちいち>>29するのはコードが面倒になると思うので、
sync=true したファイルIOオブジェクトを $stdout に指定しろ
31:デフォルトの名無しさん
09/07/04 12:55:32
>>28
本筋とは関係ないけど、たぶんそれSTDOUTをdupする必要はないな
$stdout = STDOUT
でおk
32:デフォルトの名無しさん
09/07/04 12:59:17
元に戻すならsv = $stdoutのほうがいいような
まあどちらにしてもdupは要らんね
33:デフォルトの名無しさん
09/07/04 13:07:04
>>29
やってみましたが、結果は同じでした・・
>>30
下手な質問で申し訳ありません;
>・ ファイルに出力するよモードになったときはファイルに出力
>・ ファイルに出力するよモードじゃないときは標準出力に出力
>・ これを $stdout への代入だけで切り替えたい
で合っています
が、やはりできませんでした
すいません・・
>>31
>>32
わかりました
やり直してみます
みなさんありがとうございます
34:デフォルトの名無しさん
09/07/04 13:29:26
f = File.open("ファイル名", "w")
f.sync = true
$stdout = f
これでなんとかなんね?
35:デフォルトの名無しさん
09/07/04 13:42:35
>>34
できませんね…
自分がLinux初心者のため、出来たファイルを開く際、文字コードに関する不具合(文字化けとか)によって
中身がおかしいのかもしれないです
別の方法でやってみますね
助けてくださってありがとうございました
36:デフォルトの名無しさん
09/07/04 13:49:26
よくわからんけど、グローバルな$stdoutに代入していいのかにょ?
37:デフォルトの名無しさん
09/07/04 13:51:54
代入できるように定数とグローバルの両方が存在してる
38:デフォルトの名無しさん
09/07/04 13:53:38
>>37
おk把握
39:デフォルトの名無しさん
09/07/04 15:54:40
たのしいRubyを読んでいます。
クラスとモジュールの違いがよく理解きないです。
解りやすく教えてほしいです。
40:デフォルトの名無しさん
09/07/04 16:01:27
違う本よめ
41:デフォルトの名無しさん
09/07/04 16:05:53
クラス
普段使うもの
処理を分類したもの(メソッド)を起動するオブジェクトの生成器
基本的にはこれだけで生きていける
モジュール
普段使わない
ガチ初心者のうちは自分から作らなくてもいいというかむしろ忘れろ
initialize できない(そもそも作れない)
クラスAとクラスBに共通メソッド群Mを持たせたいという場合、Mをモジュールにすると楽
クラスMを作って継承しても用が済むことがほとんどだが、モジュールにしたほうが本当はいい
42:デフォルトの名無しさん
09/07/04 16:07:53
クラスはモジュールの一種
つまりクラスはモジュールとしての機能を全て持っていて
その上で、特別にインスタンス化することができる
具体的には、あのnewってのができる
43:デフォルトの名無しさん
09/07/04 16:09:21
必ず親があるのがクラス(親を指定しなければObject)、親のないのがモジュール。
継承して使うのがクラス、includeして使うのがモジュール。
Classクラスのインスタンスなのがクラス、Moduleクラスのインスタンスなのがモジュール。
ModuleはClassのスーパークラス。
44:デフォルトの名無しさん
09/07/04 16:18:15
初心者スレ的には>>41に一票
まーあれだ、半年くらいダラダラ使ってればある日突然わかるからあんま心配すんな
日常的には「よくわからんけど○○らしい」程度の理解で充分
45:デフォルトの名無しさん
09/07/04 17:02:41
>>28
同じようなことしてるけど、
#最初
$stdout=File.open("filename""w")
出力
#最後
$stdout=STDOUT
ってなってた。
46:デフォルトの名無しさん
09/07/04 17:35:52
ある日突然オブジェクト脳が閃く感じか。
47:デフォルトの名無しさん
09/07/04 18:42:42
すべてはClassクラスのインスタンスということで良いのでしょうか?
Ruby1.9.1では、BasicObject、Object、Class、Moduleもすべて。
48:デフォルトの名無しさん
09/07/04 19:01:08
…あんまそんなこと気にしないほうがええぞ
49:デフォルトの名無しさん
09/07/04 19:17:11
>>48に同意しつつも答えとく
>>47
>すべてはClassクラスのインスタンス
とりあえず
class Foo; end
は暗黙的にObjectを継承するし
obj = Foo.new
のobjはObjectインスタンスの性質も多く含むけど(というかこの場合そのまんま)
あくまでもobjはFooのインスタンスであってObjectのインスタンスとは呼ばない
という前置きをした上で
全てのクラスそのものがClassインスタンスっていうのは正しい
Object.new.class #=> Object
Object.class #=> Class
「インスタンスを生成する役割を持つもの」がClassクラスのインスタンスであり
Rubyではそれを「クラス」と呼ぶ
でもそれによって生成されたインスタンスは「クラス」ではない
もちろんClassのインスタンスという特例は除く
50:デフォルトの名無しさん
09/07/04 19:39:58
>>49
Rubyではすべてがオブジェクトであるという文言が
気になった次第です。
>>48
Classクラスのインスタンスはクラスオブジェクト(Object、Fooなど)
ということになるんですね。
クラス(Class)のインスタンスがクラスオブジェクト(Foo)で、
クラスオブジェクトFooもまたインスタンスを生成してと。。
やはり必要時以外は考えないようにします。
51:39
09/07/04 22:06:38
みなさん、ありがとうございました。
けっこう、すっきりしました。
52:デフォルトの名無しさん
09/07/04 23:11:56
その辺のぼやーんとした認識に直視せざるを得なくなる本が
プログラミング言語Ruby
凄い濃い本だが確かに初心者にはお勧め出来ない
53:デフォルトの名無しさん
09/07/04 23:38:46
まああれは
どの言語にも一冊はあるような「しっかりした本」だから・・・・・・
細かい挙動を確かめたくなった時に、手にとればいい
54:デフォルトの名無しさん
09/07/05 12:18:05
class Widget
def initialize(x, y)
@x = x
@y = y
end
end
インスタンス変数に @x = x と書くのと self.x = x は同じ意味ですか?
55:デフォルトの名無しさん
09/07/05 12:26:40
この場合のメソッド定義内で書く self.x = は インスタンスメソッド Widget#x= を起動する
インスタンスメソッド Widget#x= の内部でインスタンス変数 @x にアクセスしてるかどうかは x= の定義による
56:デフォルトの名無しさん
09/07/05 12:29:15
おそらく、自メソッドの引数 x と被るインスタンスメソッド x を起動したいんだが、
そのまま x とだけ書くと引数の変数 x にアクセスしてしまうので
それを避けるために明示的にメソッド x を指示したいのだろう
57:デフォルトの名無しさん
09/07/05 12:39:56
class C
def initialize(x)
puts "x は #{x} です"
puts "self.x は #{self.x} です"
end
def x
return "メソッド"
end
end
C.new('引数')
結果
x は 引数 です
self.x は メソッド です
58:デフォルトの名無しさん
09/07/05 12:44:38
>>55
>>56
レスありがとうございます。
セッター(x=、attr_writer、attr_accessor) を明示的に定義しなければ、self.x は
def x=(x)
@x = x
end
が実行されたのと等価なので、結果は同じということですよね。
59:デフォルトの名無しさん
09/07/05 12:49:26
>>57
レスありがとうございます。
僕はゲッター、セッター
hoge = self.x
self.x = poge
がメソッドだというのを忘れがちです。
60:58
09/07/05 12:51:43
>>58
セッター(x=、attr_writer、attr_accessor) を明示的に定義しなければ
これはウソでした。
セッターattr_writer、attr_accessor は必要です。
61:デフォルトの名無しさん
09/07/05 13:19:27
他の言語にあるセッターやゲッターというものはRubyには存在しない
あれはただの値を返すメソッドで、attr* はメソッド定義を肩代わりする略記に過ぎない
module AttrReader
def attr_reader(arr)
arr.each do |method_name|
eval("def #{method_name}
return @#{method_name}
end")
end
end
end
class C
include AttrReader
attr_reader([:x])
end
と
class C
attr_reader :x
end
はリクツ上おおむね同じ動作をする
attr* を使う動作上のメリットというのは何もない
メソッド定義書くのがちょっと短縮されるというだけだったりする
62:デフォルトの名無しさん
09/07/05 13:40:03
>>61
なるほど。
だからreader、writerと呼ばれるんですかね。
63:デフォルトの名無しさん
09/07/05 14:36:28
Ruby作者ってしゃべりかたが変わっていないか?
なにか障害をもっているの?
64:デフォルトの名無しさん
09/07/05 14:38:34
早口なだけじゃね?
俺もリアル世界では早口って言われる。
相手が聞き取りやすいようにゆっくり話すように心がけているが ...orz
65:デフォルトの名無しさん
09/07/05 14:41:45
>>63
matzのことなら、最低限一般水準程度には普通に、また俺的にはとても知性的にかつ
フレンドリーに喋ったり発信しているように見受けられる
まあコミュニケーションには受け手の問題もあるのは知ってるので、>>63の見解も
頭から否定する気はないが
66:デフォルトの名無しさん
09/07/05 14:43:16
誰だったかが言うには
「頭の回転が速すぎて口が追いついてない」
67:デフォルトの名無しさん
09/07/05 14:48:42
どうしてIBMとか大企業に就職しなかったの?
68:デフォルトの名無しさん
09/07/05 14:49:37
隔離スレでやれ
69:デフォルトの名無しさん
09/07/05 14:52:51
ここだな。同意
スレリンク(tech板)
70:デフォルトの名無しさん
09/07/05 14:53:20
>>67
飼い慣らされると痛い目に遭うから、だと思う。
71:デフォルトの名無しさん
09/07/05 15:08:55
>>67
在学中に有名になってしまって、就職する必要がなくなった。
72:デフォルトの名無しさん
09/07/05 16:48:57
>>71
??
chainmail?
73:デフォルトの名無しさん
09/07/05 19:32:27
単に入社試験で落とされたとかだろ。
74:デフォルトの名無しさん
09/07/05 19:34:54
クリエイターとして生きることができた人に「どうして就職しなかったんですか」というのは単なる愚問だ
就職しなくても生きられたから就職しなかったというだけに過ぎない
75:デフォルトの名無しさん
09/07/05 20:40:04
なんか特定の条件のときに特定の TestCase クラスのユニットテストを実行しないという芸当は可能ですか
76:デフォルトの名無しさん
09/07/05 20:43:40
test_ で始まるメソッドを undef すればいいんじゃね
77:デフォルトの名無しさん
09/07/05 21:30:21
既存のクラスのメソッド定義を、include のようなものであとから書き換えることはできますか?
対象となるクラスは既に他のクラスを継承してるので、追加メソッド群をクラスにして継承してもらうことはできません。
78:デフォルトの名無しさん
09/07/05 21:42:39
該当クラスのオブジェクトが生成されるより前に、
「該当クラス定義を再オープンしてメソッド定義を書き換える」というeval系の何かを適当に実行
79:デフォルトの名無しさん
09/07/05 21:55:03
>>77
普通にdefするだけじゃだめなの?
class A < S
end
class A
def extra_method
end
end
もしくは、単にincludeするとか
80:デフォルトの名無しさん
09/07/05 22:06:15
>>79
includeでクラスのメソッド定義を上書きできるとは初耳だな
81:デフォルトの名無しさん
09/07/06 01:01:03
>>80
superclassよりは優先されるから一応は出来る
自身のメソッド定義は覆せないけどね
「既存のクラス」の名前を決め打ちで利用されてるのではなければ
もう一度継承して(「既存のクラス」をsuperclassにして)からincludeすればいい
決め打ちされてるなら・・・>>79の方法になるんじゃないかなぁ
とてもお勧めできない方法
class Foo; end
class Bar < Foo; end
Foo = Bar
Foo.new.class #=> Bar
82:デフォルトの名無しさん
09/07/06 01:18:46
>>77の質問の意味がいまいち良くわからないんだよねえ
具体的なコード片とかが無いとどう困ってるのかわからなくて答えにくい
83:デフォルトの名無しさん
09/07/06 01:24:10
まあ全くお勧めしないが
module Hoge
def included(c)
c.class_eval do
alias fuga_original fuga
def fuga; (処理) end
end
end
end
とかやったのをincludeすればいけるかもしれない
84:デフォルトの名無しさん
09/07/06 02:44:40
open-uriに関する質問です。
特定のurlで下記のスクリプトがエラーを出力します。
エラー文: `close': closed stream (IOError)
============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}
url = 'URLリンク(gimpo.2ch.net)' # errorが起きる
url2 = 'URLリンク(anchorage.2ch.net)' # errorが起きない
url3 = 'URLリンク(gimpo.2ch.net)' # errorが起きる
open(url, header) do |io|
Zlib::GzipReader.wrap(io) do |gz|
puts gz.read # urlの中身が出力されたあとにerrorが起きる
end
end
============= ここまで ============
open-uri, zlib, 2chの鯖のどこに問題があるのでしょうか?
openのブロック付き呼び出しの中でさらに別のIOオブジェクトをブロック付きで呼び出していることが原因なのかと考えたのですが、
特定のurlでのみ起きる理由が分かりません・・・。
85:デフォルトの名無しさん
09/07/06 02:46:08
ちなみに↓のスクリプトではエラーが起きません。
============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}
url = 'URLリンク(gimpo.2ch.net)' # errorが起きる
url2 = 'URLリンク(anchorage.2ch.net)' # errorが起きない
url3 = 'URLリンク(gimpo.2ch.net)' # errorが起きる
open(url, header) do |io|
Zlib::GzipReader.wrap(io).readlines.each do |line|
puts line
end
end
============= ここまで ============
86:デフォルトの名無しさん
09/07/06 03:27:42
>>84
Zlib::GzipReader.wrapが自動的にioをcloseし
さらにopenのブロック実行後にioをcloseしようとするから
IOErrorが出るのは正しい動作
url2でエラーが出ない方がおかしいんだけど何故かはわからん
要するにcloseが二回実行されないようにすればいいんだが
それはリファレンスマニュアルでZlib::GzipReader.wrapの所を嫁
87:デフォルトの名無しさん
09/07/06 04:02:24
>86
レスありがとうございます。
解決策のほうも分かりました。
ところで>85の例でエラーが出なかった理由は
Zlib::GzipReader.wrapがcloseされていなかったからioもcloseされず、ioがopenによって正しくcloseされたからという理解でよろしいでしょうか?
IOオブジェクトを用いる場合には
file = IO.open(foo)
begin
<処理>
ensure
file.close
end
IO.open(foo) do |io|
<処理>
end
のどちらかで記述するというのが常識ですが、
IO.open(foo).read のような使い方をするとそのIOオブジェクトはcloseすることができなくなってしまうのでしょうか?
重ね重ねの質問ですが、長らくの疑問で調べても分からなかったのでご回答いただけるとありがたいです。
88:デフォルトの名無しさん
09/07/06 04:52:41
> ところで>85の例でエラーが出なかった理由は ...
あってる
> IO.open(foo).read ...
これではIOインスタンスへの参照がないからcloseしようがない、開きっぱなし
data = (io = IO.open(foo)).read とすればio.close出来るけど普通はIO.read(foo)とするな
ほっとけばGCが何とかしてくれると聞いたような違ったような?
89:デフォルトの名無しさん
09/07/06 05:08:25
ぬ
`close': closed stream (IOError) は、おーざっぱには
「閉じようと思ったIOオブジェクトが何者かによって既に閉じられてました姉さん事件です」
エラーだ
Zlib の close は引数の IO オブジェクトごと close する
通常は超親切機能なんだが、引数の IO オブジェクトがブロックつきだった場合、
IO 側のメソッドのブロックの ensure で行われる io.close で「既に閉じられてた」エラーが起こる
Zlib のブロックの最後で明示的に Zlib::GzipFile#finish を呼ぶと、厄介な Zlib::GzipFile#close は起動されない
…というようなことが、Zlib::GzipReader の GzipReader.wrap のマニュアルのとこに書いてあるぞ
URLリンク(www.ruby-lang.org)
>>84
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}
url = 'URLリンク(gimpo.2ch.net)'
url2 = 'URLリンク(anchorage.2ch.net)'
url3 = 'URLリンク(gimpo.2ch.net)'
[url,url2,url3].each do |url|
open(url, header) do |io|
Zlib::GzipReader.wrap(io) do |gz|
p gz.read
gz.finish # ここ!
end
end
end
90:デフォルトの名無しさん
09/07/06 09:30:36
UTF-8 文字列に対する NKF.guess がだいたいいい感じに動作する文字数って何文字くらい?
irb> NKF.guess("ねこだいす")
5
irb> NKF.guess("ねこだいすき")
6
irb> NKF.guess("ねこだいすきっ")
5
とかいう結果でちょっとぐんにょりしてるので
91:デフォルトの名無しさん
09/07/06 09:36:09
これは非常に有名な話だが、読点を入れると NKF.guess の誤認識の確率が素晴らしく減る
irb> NKF.guess("ねこ、だ")
6
irb> NKF.guess("ねこ、だい")
6
irb> NKF.guess("ねこ、だいす")
6
irb> NKF.guess("ねこ、だいすき")
6
irb> NKF.guess("ねこ、だいすきっ")
6
irb> NKF.guess("、")
6
ということで、読点入れた文章使え
92:デフォルトの名無しさん
09/07/06 09:37:46
nkfにバグのあるバージョンのrubyを使ってないか?
最近ruby-talkでそんな話題があった気がするが。
93:92
09/07/06 09:39:16
1.8.7 patchlevel 160 ではこんな感じ
irb(main):002:0> NKF.guess("ねこだいす")
=> 6
irb(main):003:0> NKF.guess("ねこだいすき")
=> 6
irb(main):004:0> NKF.guess("ねこだいすきっ")
=> 6
94:デフォルトの名無しさん
09/07/06 09:55:04
文字列を自由に設定できるのなら読点入れるのが間違いないとは思う
95:デフォルトの名無しさん
09/07/06 09:58:22
それならそもそもguessする必要ないだろ
96:デフォルトの名無しさん
09/07/06 10:19:41
字句解析には、まともに使えないってことだな。
97:デフォルトの名無しさん
09/07/06 10:28:41
文字コード推定と字句解析の関連をkwsk
98:デフォルトの名無しさん
09/07/06 10:52:17
Mule や Emacs が、読み込んだファイルの文字コードを自動判定するのは
ご存じだと思うが、Meadow 2 や Meadow 3は、 UTF-8 のファイルの文字コードを、けっこう間違える。
一方、秀丸はほぼ絶対間違えない。
これらの違いは何だろうかということと、同じような実装をNKF でもできないのかな?と思った。
99:デフォルトの名無しさん
09/07/06 10:55:06
ほうほう、つまり CP932 と UTF-8 以外の優先度を下げろと
100:98
09/07/06 11:05:55
いや、そういうつもりはない、というか秀丸とかは、内部でそういう実装になっていたのか。
知らなかったよ
101:デフォルトの名無しさん
09/07/06 11:12:29
結果的に正しく判断される確率が高い方がいい
102:デフォルトの名無しさん
09/07/06 12:04:51
そのためには文脈情報が要るんだよ
HTML だったら charset 読んでみるとか
句読点が改行文字の直前にあったら日本語だと思ってみるとか
東欧辞書にマッチするバイト列が頻出したら Latin-2 だと思ってみるとか
Iconv が guess に該当する機能を一切提供してないのは手抜きじゃなくて必然
多エンコーディングに対応すればするほど指数関数的に推測のコストは上がる
日本語だけ取っても Shift_JIS と CP932 と EUC-JP と EUC-JP-MS の4つを区別するのは至難
っていうか規格をちょっとずつ混ぜるなめんどくさいから
あとケータイ絵文字入り文字列をキャリア情報なし端末情報なしの素で送ってくる奴は即死刑で
103:デフォルトの名無しさん
09/07/06 12:33:21
次の質問の人どうぞ
104:デフォルトの名無しさん
09/07/06 15:37:50
/usr/local/lib/ruby1.9/1.9.1/minitest/unit.rb:359:in `puke':
incompatible character encodings: UTF-8 and ASCII-8BIT (Encoding::CompatibilityError)
イライラ
105:デフォルトの名無しさん
09/07/06 15:54:27
rrseをUTF8で使うにはどうすればいいですか?
106:デフォルトの名無しさん
09/07/06 15:56:26
>>104
Ruby1.9向けテストで「なんかどっか書き間違ってる」時に出るやつだな
具体的にどのへんの行で詰まってるとかヒントぜんぜんなし
かろうじて -v でテストのメソッド名が出るくらい
107:デフォルトの名無しさん
09/07/06 15:58:00
>>105
rdoc のファイルと同じエンコーディングを -K とかで指定すればいいんじゃね
108:デフォルトの名無しさん
09/07/06 16:09:03
>89
詳細な解説ありがとうございます。
ためになりました。
>88
>普通はIO.read(foo)とするな
IOオブジェクトを簡単に読み取るにはこの方法を使えばいいんですね。
しかしopen-uriで拡張されたopenには同等のメソッドがありませんね。
URI.parse(foo)がIO.read(foo)と同等のことができますが、
URI.parseはHTTPリクエストのオプションをつけて動かすことができないんですよね。
URI.parse(uri, 'hogehoge' => 'foobar')のように。
アドバイスをいただき>84での問題は解決したのですが次の問題が発生してしまいました。。
109:デフォルトの名無しさん
09/07/06 16:09:48
下記のスクリプトがエラーを吐きます。
エラー文: `initialize': buffer error (Zlib::BufError)
困ったことに、通ったり通らなかったりします。
原因はたぶんですが2chのサーバが出力しているgzip圧縮したsubject.txtのほうだと思います。
板内のスレいずれかにカキコミがあればsubject.txtは書き換わるため、通る場合と通らない場合があるのだと予想しています。
しかしエラー文の意味がよく分からず、どのように回避すればよいのかが分かりません。
ちなみに拾ってきたgzip化subject.txtファイルをHDDに書き込んでアーカイバで開くと正しく読み取れています。
============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}
url = 'URLリンク(gimpo.2ch.net)' # errorが一度も起きていない
url2 = 'URLリンク(gimpo.2ch.net)' # errorが起きたり起こらなかったりする
open(url, header) do |io|
Zlib::GzipReader.wrap(io) do |gz|
puts gz.read # urlの中身が出力されたあとにerrorが起きる
end
end
============= ここまで ============
110:デフォルトの名無しさん
09/07/06 16:19:50
>>109
原因は一発でわかったが、そろそろあんま話したくない
HTTPの知識のない状態でなに作る気なん?
111:デフォルトの名無しさん
09/07/06 16:23:31
別にいいじゃん。初心者スレなんだし。
答えるのいやなら他行けば?
112:デフォルトの名無しさん
09/07/06 16:25:29
libwww-perlの轍踏む気にはならんね
113:デフォルトの名無しさん
09/07/06 16:29:29
まあサイトや回線にどんだけ負荷かけて裁判起こされようが知ったこっちゃないが、
このへんがわかんないのはそもそも辛いと思うんだがどう
open-uri で open してテキストを read する以外の事をしようと思うなら、別途勉強がいると思う
114:デフォルトの名無しさん
09/07/06 16:36:36
2chにアクセスするアプリケーションは自力で調べて作ってもらうというのが一応不文律だったりする
115:デフォルトの名無しさん
09/07/06 16:43:06
>>109
open-uriは便利に見えるけどハマると厄介、net/httpの使い方をおぼえろ
res = Net::HTTP.get_response(URI(url))
txt = res.body
if res['content-encoding'] =~ /gzip/
txt = Zlib::GzipReader.wrap(StringIO.new(txt)) {|gz| gz.read }
end
puts txt
>>110
原因を教えてもらえないだろうか?
うちの環境では例外が発生しないので問題がわからない
116:デフォルトの名無しさん
09/07/06 16:43:45
content-encoding見てないのはマズいと思うけど
>>109はHTTPレベルの問題じゃないような
117:デフォルトの名無しさん
09/07/06 16:45:14
付け加えておくとgzじゃないものを食わせた時は
Zlib::GzipFile::Error: not in gzip format
118:デフォルトの名無しさん
09/07/06 16:47:52
もなじら名乗ってない時点で問題外
119:デフォルトの名無しさん
09/07/06 16:49:01
>109のスクリプトを書き間違えていました。
============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}
url = 'URLリンク(gimpo.2ch.net)' # errorが一度も起きていない
url2 = 'URLリンク(gimpo.2ch.net)' # errorが起きたり起こらなかったりする
open(url, header) do |io|
Zlib::GzipReader.wrap(io) do |gz|
puts gz.read # urlの中身が出力されたあとにerrorが起きる
gz.finish #<= 書き忘れ
end
end
============= ここまで ============
>110
2chのスレのdatを収集するプログラムです。
たまに気がつくとスレが1001になってdat落ちしてしまって、最後に開いた地点までしか読めなくなるのが悲しいので、
過去に開いたことがあるスレを定期的に拾いなおしてくれるプログラムを作りたいと思いまして。
プログラム自体は完成していて意図した通りに動くのですが、
転送量を少しでも削減したくてdatだけではなくsubject.txtを拾うときにgzip化しようと欲を出したらうまくいかなくなりました。
120:デフォルトの名無しさん
09/07/06 16:54:41
スレ更新をせず書き込んでしまいました。
>113
一応、DLする度にsleep 1.0 を入れています。
これでは不十分でしょうか?
>114
それは大変失礼しました。
今後は自力解決したいと思います。
>115
datの取得ではnet/httpを使っています。
一つのdomainから複数のファイルを拾うときにはnet/http, 1つのファイルを拾うだけならopen-uriというふうに使い分けていました。
121:115
09/07/06 17:17:01
header渡してなかった
txt = URI(url).read(header)
if txt.content_encoding.include?('gzip')
: