[表示 : 全て 最新50 1-99 101- 2chのread.cgiへ]
Update time : 05/10 00:24 / Filesize : 38 KB / Number-of Response : 122
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

Ruby 初心者スレッド Part 29



1 名前:デフォルトの名無しさん mailto:sage [2009/07/03(金) 12:55:05 ]
プログラミング言語Rubyについての、初心者向けスレです。質問・要望・雑談などどうぞ。

   【Ruby1.9.1 は従来版とは異なる部分も多く、書籍や解説やライブラリのサポートがまだありません】
   【自力で解決できない壁で悩むことのない最新安定版の Ruby1.8.7 での学習をお勧めします】
    ※1.8.7 は 1.8 系と 1.9 系の橋渡しをするためのリリースで、1.9 系 の便利新機能の一部が利用可能です

関連スレやURLは>>2-5あたりを見てください。Ruby on Rails の質問は Webプログラミング板の Rails スレへ。

■質問する人へ
質問する前に次の3つをすること。ここで回答を待つよりそのほうが早い。
 ・モジュール名やエラーメッセージでググる
 ・マニュアルで引っかかったクラスの記述を探す www.ruby-lang.org/ja/man/
 ・FAQを一応読む www.ruby-lang.org/ja/man/?cmd=view;name=Ruby+FAQ
質問には以下を書くこと。へたくそな質問は再提出を要求される。
 ・詳しい内容(「動きません」「うまくできません」では回答しようがない)
 ・エラーメッセージ(自力で訳さずなるべくそのままで)
 ・実行環境(OS名、Rubyのバージョン(ruby -v でわかる))
 ・最終的にやりたいこと(もっとよい方法がある場合が多いので)
回答してくれた人には「ありがとう」のひとことをいってあげて。
■回答する人へ
相手は初心者、根気よく育てるつもりで。質問がへたくそなのも大目にみてあげる。
それができないならこないこと(だって初心者スレだもん)。
 ・既出な質問やFAQは「XXXを読め」でいいので、叩かない&怖がらせない。
 ・わけわかな質問にもエスパー発揮で。できれば質問の仕方を教えるぐらいで。
 ・自信がない回答ならその旨表明すること。誤った回答は初心者じゃ見抜けない。

63 名前:デフォルトの名無しさん [2009/07/05(日) 14:36:28 ]
Ruby作者ってしゃべりかたが変わっていないか?
なにか障害をもっているの?

64 名前:デフォルトの名無しさん [2009/07/05(日) 14:38:34 ]
早口なだけじゃね?

俺もリアル世界では早口って言われる。
相手が聞き取りやすいようにゆっくり話すように心がけているが ...orz

65 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 14:41:45 ]
>>63
matzのことなら、最低限一般水準程度には普通に、また俺的にはとても知性的にかつ
フレンドリーに喋ったり発信しているように見受けられる
まあコミュニケーションには受け手の問題もあるのは知ってるので、>>63の見解も
頭から否定する気はないが

66 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 14:43:16 ]
誰だったかが言うには
「頭の回転が速すぎて口が追いついてない」

67 名前:デフォルトの名無しさん [2009/07/05(日) 14:48:42 ]
どうしてIBMとか大企業に就職しなかったの?

68 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 14:49:37 ]
隔離スレでやれ

69 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 14:52:51 ]
ここだな。同意
ttp://pc12.2ch.net/test/read.cgi/tech/1246174168/

70 名前:デフォルトの名無しさん [2009/07/05(日) 14:53:20 ]
>>67
飼い慣らされると痛い目に遭うから、だと思う。

71 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 15:08:55 ]
>>67
在学中に有名になってしまって、就職する必要がなくなった。



72 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 16:48:57 ]
>>71
??
chainmail?


73 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 19:32:27 ]
単に入社試験で落とされたとかだろ。

74 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 19:34:54 ]
クリエイターとして生きることができた人に「どうして就職しなかったんですか」というのは単なる愚問だ
就職しなくても生きられたから就職しなかったというだけに過ぎない

75 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 20:40:04 ]
なんか特定の条件のときに特定の TestCase クラスのユニットテストを実行しないという芸当は可能ですか

76 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 20:43:40 ]
test_ で始まるメソッドを undef すればいいんじゃね

77 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 21:30:21 ]
既存のクラスのメソッド定義を、include のようなものであとから書き換えることはできますか?
対象となるクラスは既に他のクラスを継承してるので、追加メソッド群をクラスにして継承してもらうことはできません。

78 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 21:42:39 ]
該当クラスのオブジェクトが生成されるより前に、
「該当クラス定義を再オープンしてメソッド定義を書き換える」というeval系の何かを適当に実行

79 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 21:55:03 ]
>>77
普通にdefするだけじゃだめなの?

class A < S
end

class A
 def extra_method
 end
end

もしくは、単にincludeするとか

80 名前:デフォルトの名無しさん mailto:sage [2009/07/05(日) 22:06:15 ]
>>79
includeでクラスのメソッド定義を上書きできるとは初耳だな

81 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 01:01:03 ]
>>80
superclassよりは優先されるから一応は出来る
自身のメソッド定義は覆せないけどね

「既存のクラス」の名前を決め打ちで利用されてるのではなければ
もう一度継承して(「既存のクラス」をsuperclassにして)からincludeすればいい

決め打ちされてるなら・・・>>79の方法になるんじゃないかなぁ

とてもお勧めできない方法
class Foo; end
class Bar < Foo; end
Foo = Bar
Foo.new.class #=> Bar



82 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 01:18:46 ]
>>77の質問の意味がいまいち良くわからないんだよねえ
具体的なコード片とかが無いとどう困ってるのかわからなくて答えにくい

83 名前:デフォルトの名無しさん mailto:sage [2009/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 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 02:44:40 ]
open-uriに関する質問です。
特定のurlで下記のスクリプトがエラーを出力します。
エラー文: `close': closed stream (IOError)

============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}

url = 'gimpo.2ch.net/bakery/subject.txt' # errorが起きる
url2 = 'anchorage.2ch.net/live/subject.txt' # errorが起きない
url3 = 'gimpo.2ch.net/salt/subject.txt' # 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 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 02:46:08 ]
ちなみに↓のスクリプトではエラーが起きません。

============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}

url = 'gimpo.2ch.net/bakery/subject.txt' # errorが起きる
url2 = 'anchorage.2ch.net/live/subject.txt' # errorが起きない
url3 = 'gimpo.2ch.net/salt/subject.txt' # errorが起きる

open(url, header) do |io|
 Zlib::GzipReader.wrap(io).readlines.each do |line|
  puts line
 end
end
============= ここまで ============

86 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 03:27:42 ]
>>84
Zlib::GzipReader.wrapが自動的にioをcloseし
さらにopenのブロック実行後にioをcloseしようとするから
IOErrorが出るのは正しい動作
url2でエラーが出ない方がおかしいんだけど何故かはわからん

要するにcloseが二回実行されないようにすればいいんだが
それはリファレンスマニュアルでZlib::GzipReader.wrapの所を嫁

87 名前:デフォルトの名無しさん mailto:sage [2009/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 名前:デフォルトの名無しさん mailto:sage [2009/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 名前:デフォルトの名無しさん mailto:sage [2009/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 のマニュアルのとこに書いてあるぞ
ttp://www.ruby-lang.org/ja/man/html/Zlib_GzipReader.html#GzipReader.2ewrap

>>84
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}

url = 'gimpo.2ch.net/bakery/subject.txt'
url2 = 'anchorage.2ch.net/live/subject.txt'
url3 = 'gimpo.2ch.net/salt/subject.txt'

[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 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 09:30:36 ]
UTF-8 文字列に対する NKF.guess がだいたいいい感じに動作する文字数って何文字くらい?

irb> NKF.guess("ねこだいす")
5
irb> NKF.guess("ねこだいすき")
6
irb> NKF.guess("ねこだいすきっ")
5

とかいう結果でちょっとぐんにょりしてるので

91 名前:デフォルトの名無しさん mailto:sage [2009/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 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 09:37:46 ]
nkfにバグのあるバージョンのrubyを使ってないか?
最近ruby-talkでそんな話題があった気がするが。

93 名前:92 mailto:sage [2009/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 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 09:55:04 ]
文字列を自由に設定できるのなら読点入れるのが間違いないとは思う

95 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 09:58:22 ]
それならそもそもguessする必要ないだろ

96 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 10:19:41 ]
字句解析には、まともに使えないってことだな。

97 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 10:28:41 ]
文字コード推定と字句解析の関連をkwsk

98 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 10:52:17 ]
Mule や Emacs が、読み込んだファイルの文字コードを自動判定するのは
ご存じだと思うが、Meadow 2 や Meadow 3は、 UTF-8 のファイルの文字コードを、けっこう間違える。

一方、秀丸はほぼ絶対間違えない。

これらの違いは何だろうかということと、同じような実装をNKF でもできないのかな?と思った。

99 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 10:55:06 ]
ほうほう、つまり CP932 と UTF-8 以外の優先度を下げろと

100 名前:98 mailto:sage [2009/07/06(月) 11:05:55 ]
いや、そういうつもりはない、というか秀丸とかは、内部でそういう実装になっていたのか。
知らなかったよ

101 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 11:12:29 ]
結果的に正しく判断される確率が高い方がいい



102 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 12:04:51 ]
そのためには文脈情報が要るんだよ

HTML だったら charset 読んでみるとか
句読点が改行文字の直前にあったら日本語だと思ってみるとか
東欧辞書にマッチするバイト列が頻出したら Latin-2 だと思ってみるとか

Iconv が guess に該当する機能を一切提供してないのは手抜きじゃなくて必然
多エンコーディングに対応すればするほど指数関数的に推測のコストは上がる

日本語だけ取っても Shift_JIS と CP932 と EUC-JP と EUC-JP-MS の4つを区別するのは至難
っていうか規格をちょっとずつ混ぜるなめんどくさいから
あとケータイ絵文字入り文字列をキャリア情報なし端末情報なしの素で送ってくる奴は即死刑で

103 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 12:33:21 ]
次の質問の人どうぞ

104 名前:デフォルトの名無しさん mailto:sage [2009/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 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 15:54:27 ]
rrseをUTF8で使うにはどうすればいいですか?

106 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 15:56:26 ]
>>104
Ruby1.9向けテストで「なんかどっか書き間違ってる」時に出るやつだな
具体的にどのへんの行で詰まってるとかヒントぜんぜんなし
かろうじて -v でテストのメソッド名が出るくらい

107 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 15:58:00 ]
>>105
rdoc のファイルと同じエンコーディングを -K とかで指定すればいいんじゃね

108 名前:デフォルトの名無しさん mailto:sage [2009/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 名前:デフォルトの名無しさん mailto:sage [2009/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 = 'gimpo.2ch.net/bakery/subject.txt' # errorが一度も起きていない
url2 = 'gimpo.2ch.net/kagu/subject.txt' # errorが起きたり起こらなかったりする

open(url, header) do |io|
 Zlib::GzipReader.wrap(io) do |gz|
  puts gz.read # urlの中身が出力されたあとにerrorが起きる
 end
end
============= ここまで ============

110 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:19:50 ]
>>109
原因は一発でわかったが、そろそろあんま話したくない
HTTPの知識のない状態でなに作る気なん?

111 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:23:31 ]
別にいいじゃん。初心者スレなんだし。
答えるのいやなら他行けば?



112 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:25:29 ]
libwww-perlの轍踏む気にはならんね

113 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:29:29 ]
まあサイトや回線にどんだけ負荷かけて裁判起こされようが知ったこっちゃないが、
このへんがわかんないのはそもそも辛いと思うんだがどう
open-uri で open してテキストを read する以外の事をしようと思うなら、別途勉強がいると思う

114 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:36:36 ]
2chにアクセスするアプリケーションは自力で調べて作ってもらうというのが一応不文律だったりする

115 名前:デフォルトの名無しさん mailto:sage [2009/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 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:43:45 ]
content-encoding見てないのはマズいと思うけど
>>109はHTTPレベルの問題じゃないような


117 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:45:14 ]
付け加えておくとgzじゃないものを食わせた時は
Zlib::GzipFile::Error: not in gzip format

118 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:47:52 ]
もなじら名乗ってない時点で問題外

119 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:49:01 ]
>109のスクリプトを書き間違えていました。
============= ここから ============
require 'open-uri'
require 'zlib'
header = {'accept-encoding' => 'gzip'}

url = 'gimpo.2ch.net/bakery/subject.txt' # errorが一度も起きていない
url2 = 'gimpo.2ch.net/kagu/subject.txt' # 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 名前:デフォルトの名無しさん mailto:sage [2009/07/06(月) 16:54:41 ]
スレ更新をせず書き込んでしまいました。

>113
一応、DLする度にsleep 1.0 を入れています。
これでは不十分でしょうか?

>114
それは大変失礼しました。
今後は自力解決したいと思います。

>115
datの取得ではnet/httpを使っています。
一つのdomainから複数のファイルを拾うときにはnet/http, 1つのファイルを拾うだけならopen-uriというふうに使い分けていました。

121 名前:115 mailto:sage [2009/07/06(月) 17:17:01 ]
header渡してなかった
txt = URI(url).read(header)
if txt.content_encoding.include?('gzip')
 :








[ 新着レスの取得/表示 (agate) ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧](*・∀・)<38KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef