HOME  >  2014/01

Rake で起こったエラーと対処法 wrong number of arguments (0 for 2..3) (ArgumentError)

ちょっとハマッたのでメモ。

他の方が作った GitHub 上のソースを修正して、いざテスト!と思って
rake test でテスト実施しようとしたらエラー。
C:\ruby\lib\ruby\gems\2.0.0\gems\win32-clipboard-0.6.1\test\test_html_clipboard.rb:17:
in `test': wrong number of arguments (1 for 2) (ArgumentError)
はい?テスト用のソース内で引数の個数が違うっていうエラー?
そのテスト用のソースは、いじってねーですよ……。そんな状況でした。

ちょっといろいろ調べたんですが、気がついてみれば簡単。
Rake のバージョンが古かっただけで、新しいのを入れたら解決しました。
gem install rake
# Ruby 2.0 入れてから Rake でテストするのが初だった模様。
# インストールした Ruby に(たぶん)付属していた Rake のバージョンが 0.9.6。
# gem install rake をしてみると、バージョンが 10.1.1 に……。
スポンサーサイト



2014/01/26 | カテゴリ:Ruby | トラックバック(1) | コメント(0)

Windows 上の Ruby でクリップボードを活用する方法 その2

この記事は、その 2 ですが、その 1 を見る必要はありません。
gem(win32-clipboard) がバージョンアップして、その 1 は無意味になりましたので。(せつない)

クリップボードを利用するために、win32-clipboard という gem を利用します。
gem install win32-clipboard
日本語を使うには、ちょっとだけ癖があります。
クリップボードに UNICODE として入れてあげる必要があります。
そうすると Ctrl + V のペーストでも日本語が文字化けしません。
require 'win32/clipboard'

str = "ほげほげふーばー"
Win32::Clipboard.set_data(str, Win32::Clipboard::UNICODETEXT) # <- UNICODE でクリップボードにセット
puts Win32::Clipboard.data(Win32::Clipboard::UNICODETEXT) # <- 取得時も UNICODE を指定する
2014/1/28 追記
下記は、Win32-clipboard 0.6.2 にて修正されています。
# というか修正して pull request してみました。
簡単に日本語も使えるようになりましたが、 僕の環境だと、プリントスクリーンした画像情報を読みこもうとしたらエラーになりました。
C:/ruby/lib/ruby/gems/2.0.0/gems/win32-clipboard-0.6.0/lib/win32/clipboard.rb:374:in `get_image_data': undefined local variable or method `compression' for Win32::Clipboard:Class (NameError)
        from C:/ruby/lib/ruby/gems/2.0.0/gems/win32-clipboard-0.6.0/lib/win32/clipboard.rb:117:in `data'
        from C:/Applications/ruby/clipboard/printscreen.rb:23:in `write'
if bmi[:bmiHeader][:biCompression] == 0
  table_size = bmi[:bmiHeader][:biClrUsed]
elsif compression == 3
  table_size = 3
else
  raise "invalid bit/compression combination"
end
なにやら compression なる変数が定義されてないよーということで、
以下のように修正したら動きました。
elsif bmi[:bmiHeader][:biCompression] == 3
# でも、まだビットマップ周りの処理はあやしい気がする……
2014/01/19 | カテゴリ:Ruby | トラックバック(0) | コメント(0)

Ruby 2.0 で XMLRPC を使うと発生するエラー(Wrong size)とその解決法

# 今回は Net::HTTP に関連する gem であれば他にも応用効くかもしれません。

Ruby からブログ投稿しようと思いたち、XMLRPC 使ってみればエラー発生。
過去に、Ruby 1.9.3 で動作していたものを基にしたので、エラーはおかしいということで調査開始。
C:/ruby/lib/ruby/2.0.0/xmlrpc/client.rb:506:in `do_rpc': Wrong size. Was 1802, should be 324 (RuntimeError)
        from C:/ruby/lib/ruby/2.0.0/xmlrpc/client.rb:281:in `call2'
        from C:/ruby/lib/ruby/2.0.0/xmlrpc/client.rb:262:in `call'
        from check.rb:13:in `
'
さっくり原因~解決法をまとめると、
Ruby 2.0 の XMLRPC (が使ってるNet::HTTP) では、HTTP 圧縮するのがデフォルト動作になったのに、
XMLRPC 内でレスポンスのバイトサイズをチェックする際、
無圧縮のものだと想定してバイトサイズを比較しちゃってるからエラーが発生しています。

なので、解決策は 2 通り。
  1. 最初から無圧縮でやりとりしようねってサーバとお約束する
  2. 無圧縮だと想定しちゃってるバイトサイズのチェックをどうにかする

そんなわけで、エラーが起きる条件をまとめます。
  • Ruby 2.0 以降
  • XMLRPC 使用
  • やりとりするサーバが HTTP 圧縮に対応している

原因

↓のリンク先に詳しく記載されています。(英語)
Bug #8182 - XMLRPC request fails with "Wrong size. Was 31564, should be 1501"

上でも書きましたが、ざっくりと原因のまとめ。
  1. XMLRPC は、Net::HTTP を使用している
  2. Ruby 2.0 から、Net::HTTP はデフォルトで HTTP 圧縮するように変わった
  3. XMLRPC 内に、正しく受信できたか確認するため、受信バイトサイズをチェックする処理がある
  4. 3. の処理は HTTP 圧縮のことを考慮していない
  5. HTTP 圧縮の考慮が無いため、受信バイトサイズの異常とみなされてエラー発生

お手軽解決法

HTTP 圧縮されると駄目!という状況なので、
サーバに圧縮せずそのまま送ってねーとお願いするだけです。
つまり、ヘッダの accept-encoding に identity を設定してあげれば解決です。
require 'xmlrpc/client'

server = XMLRPC::Client.new( "blog.fc2.com", "/xmlrpc.php", 80)
server.http_header_extra = {'accept-encoding' => 'identity'}  # ←これ

お手軽だけど、HTTP 圧縮されないのでその辺りのパフォーマンスを気にする方は次の解決法を。

どうしても HTTP 圧縮したい人向けの解決法

エラーチェックを削除しちゃいます。
編集するファイル: { ruby インストール先 }\lib\ruby\2.0.0\xmlrpc\client.rb
expected = resp["Content-Length"] || ""
if data.nil? or data.bytesize == 0
  raise "Wrong size. Was #{data.bytesize}, should be #{expected}"
elsif expected != "" and expected.to_i != data.bytesize and resp["Transfer-Encoding"].nil?
  raise "Wrong size. Was #{data.bytesize}, should be #{expected}"
end
※この削除の是非ですが、上で貼りつけたリンク先で議論されていて、
そもそも Net::HTTP でチェックしてんだから、ここでチェックする必要なくね?
消していいんじゃね?という結論になってます。
が、公式には、まだとりこまれてないようです。
GitHub 上の ruby 2.1.0 のソース見ても、まだ直ってないですし。……むむむ。
なので、自己責任で対応してください。

# レスポンスの Content-Encoding 見るようにして入力チェックを改造して残せば、
# まぁ安心じゃね?という方もいるかと思うのですが、
# fc2 のサーバに試しに投げてみたら、
# 何故だか Content-Encoding が空っぽで返ってきたので単純にはいかず……むむむ。
# なんか間違ったかな……。
2014/01/17 | カテゴリ:Ruby | トラックバック(0) | コメント(0)

Hit a Hint for Windows 0.5.17.4 公開

ログオン時に自動起動する際にも稀に発生していた微妙な動きを修正。
ダウンロードはこちらから

Version.0.5.17.4

  • サブモニタを接続した時など、デスクトップのサイズが変更された際、ヒントの表示位置がずれてしまうのを修正。
2014/01/15 | カテゴリ:ソフトウェア開発 | トラックバック(0) | コメント(0)

Windows 上の Ruby でクリップボードを活用する方法 その1

Ruby でクリップボードを使用する方法について。
2014/1/19 追記
2014/1/12 に win32-clipboard が更新(0.5.2->0.6.0)されて、
日本語も使えるようになっています。
ですので、この記事はもはや*無意味*です。
むむむ、なんというタイミングなんだろう……。(win32-clipboard の更新は約 4 年半ぶり)
バージョンアップした win32-clipboard の使用方法の記事も書きました。
Windows 上の Ruby でクリップボードを活用する方法 その2をご覧ください。
追記ここまで
# 今回、問題を応急処置的に対応します。
# なので、文字コードは Shift_JIS のみの対応とします。

対象:
  • Windows 上で Ruby 1.9 系以降
  • マルチバイト文字(とりあえず今回は Shift_JIS 限定)を使用している方向け
  • win32-clipboard version.0.5.2 <-2014/1/19 追記
win32-clipboard という gem を利用します。
gem install win32-clipboard
こいつ使えると便利(画像も扱えるし、クリップボード監視とかもできる)そうなんですが、
いろいろ問題があります。
問題:
  1. 画像情報を扱うとエラーが発生する場合がある
  2. 日本語を扱うと、エラーが発生する
  3. 上記エラー解決しても、日本語を扱う場合、文字が途中で途切れる
1. 3. はともかく、2. の日本語対応のためには、かなーり面倒な修正が必要になるので、
こちらの方が別の方法 (AutoITX を使う方法) を紹介しています。
Rubyからクリップボードを操作する方法
ただし AutoITX では、文字列しか扱えないっぽいので、お好きな方をお選びください。

以降では、以下のファイルを編集していきます。
{ ruby のインストール先 }\lib\ruby\gems\2.0.0\gems\win32-clipboard-0.5.2\lib\win32\clipboard.rb

1. 画像情報を扱うとエラーが発生する場合がある

実際動かしてみると、エンコードの異なる 2 つの変数を結合しようとしてエラーが発生します。
C:/ruby/lib/ruby/gems/2.0.0/gems/win32-clipboard-0.5.2/lib/win32/clipboard.rb:388:in `get_image_data': incompatible character encodings: ASCII-8BIT and US-ASCII
 (Encoding::CompatibilityError)
        from C:/ruby/lib/ruby/gems/2.0.0/gems/win32-clipboard-0.5.2/lib/win32/clipboard.rb:129:in `data'
        from C:/Applications/ruby/screenshot/printscreen.rb:23:in `write'
        from clipimagetest.rb:4:in `
'

1. 修正方法

極めて単純。
US-ASCII として Ruby に認識されちゃっている変数を、
ASCII-8BIT(BINARY) として認識させるだけです。
buf = "\x42\x4D" + [size_image].pack('L') + 0.chr * 4 + [offset].pack('L') + buf
buf = "\x42\x4D" + [size_image].pack('L') + 0.chr * 4 + [offset].pack('L') + buf.b
※ 1.9 系の場合、String#b が無いはずなので、以下のようにしてください。
buf = "\x42\x4D" + [size_image].pack('L') + 0.chr * 4 + [offset].pack('L') + buf.force_encoding('ASCII-8BIT')
やってることは、画像情報なので、buf の中身はバイナリとして扱ってねと教えてあげてるだけです。
以上で、クリップボード上の画像情報を Ruby で扱えるようになります。
require 'win32/clipboard'

if Win32::Clipboard.format_available?(Win32::Clipboard::DIB)
  File.open('image.png', 'wb'){ |f|
    f.write Win32::Clipboard.data(Win32::Clipboard::DIB)
  }
end

2. 日本語を扱おうとすると、エラー発生して使用できない

クリップボード上にある文字列を取得した際、その文字列が US-ASCII として認識されているのが原因。
C:/ruby/lib/ruby/gems/2.0.0/gems/win32-clipboard-0.5.2/lib/win32/clipboard.rb:123:in `[]': invalid byte sequence in US-ASCII (ArgumentError)
        from C:/ruby/lib/ruby/gems/2.0.0/gems/win32-clipboard-0.5.2/lib/win32/clipboard.rb:123:in `data'
        from cliptest.rb:8:in `
'

2. 修正方法(暫定)

注意:この対応は応急処置的な対応で、とりあえず Shift_JIS だけ使えるようにします。
clip_data = clip_data[ /^[^\0]*/ ]
while clip_data[clip_data.bytesize - 1] == "\0"
  clip_data.chop!
end
ただし Ruby(win32-clipboard) でコピーした文字列を
メモ帳などのエディタにペーストすると文字化けすると思います。
その場合は、以下のように String#tosjis を使ってあげると大丈夫です。
require 'win32/clipboard'
require 'kconv'

# shift_jis でクリップボードにセット
Win32::Clipboard.set_data("クリップボードにデータを設定".tosjis)
# クリップボードのデータを取得
puts Win32::Clipboard.data.tosjis
# UTF-8 でやった方が……というツッコミもあると思います。
# おっしゃるとおりだと思います。
# ただ、現状の win32-clipboard を結構改造しないと UTF-8 は扱えないのです……。
# なので、今回は見送ります。

3. 上記エラー解決しても、日本語を扱うと場合、文字が途中で途切れる

原因は、バイト数が必要になる箇所で、String#length および String#size を使用しているため。
参考:length, size (String) - Rubyリファレンス
一部を抜粋すると、
1.8 系では、文字の数はバイト数と同じになります。
1.9 系ではlengthメソッドは文字の数を返します。
バイト数を得たいときはbytesizeメソッドを使います。

3. 修正方法

String#size と String#length を String#bytesize に片っ端から修正します。
たとえば 77行目あたりを例にすると以下のように修正します。
hmem = GlobalAlloc(GHND, clip_data.length + 4)
mem  = GlobalLock(hmem)
memcpy(mem, clip_data, clip_data.length)
hmem = GlobalAlloc(GHND, clip_data.bytesize + 4)
mem  = GlobalLock(hmem)
memcpy(mem, clip_data, clip_data.bytesize)
以上で、Shift_JIS 限定ではありますが、Ruby でクリップボードが使えるようにはなります。

実は、他にも win32-clipboard にはマルチバイト文字を扱う上で妙な箇所があったりしますが、
エンコード周りは深入りしたくないので、スルー。
# たとえば bytesize + 4 の + 4 って何者!?とか。UTF-32 を考慮して + 4 してあるのかなぁ。
でも、UTF-8くらいは使えるようにしたいので、いつか、ある程度は対応したいです。
2014/01/13 | カテゴリ:Ruby | トラックバック(0) | コメント(0)

Migemize Windows 0.6.20.0 公開

migemo.dll の配置場所をユーザが指定できるようにしました。
ダウンロードはこちらから

Version.0.6.20.0

  • migemo.dll のある場所を指定できるよう設定に追加
2014/01/08 | カテゴリ:ソフトウェア開発 | トラックバック(0) | コメント(0)

Hit a Hint for Windows 0.5.16.3 公開

ログオン時に自動起動する際、稀に発生していた微妙な動きを修正。
ダウンロードはこちらから

Version.0.5.16.3

  • ログオン時の自動起動がオンのとき、稀にウィンドウがタスクバーの裏に隠れ、ヒントが見えない状態になってしまうのを修正。

2014/01/05 | カテゴリ:プログラミング | トラックバック(0) | コメント(0)

Windows 7 に Ruby 2.0 x64 を その4 ~拡張 tk の問題と対策~

4 回目の今回は、拡張 tk のインストールについて。
# Windows に限らず Mac OS X、 Linux でも同じことができます。

x86 だと、拡張 tk が入った Ruby/Tk-Kit がありますが、x64 版は見当たりません……
# というか、Ruby/Tk-Kit の本家サイトが落ちてるみたい?? x64 版も実はある??

そんなわけで x64 環境で拡張 tk を使いたい!そんなあなたに、ActiveTcl の拡張 tk。
Download Tcl: ActiveTcl Community Edition
(もちろん x64 版をダウンロードしてください)

しかし、ただインストールするだけでは使えるようにはなりません。
以下の 2 つのどちらかを行なって、Ruby から ActiveTcl のライブラリが見えるようにしてあげます。
  1. Ruby/Tk のライブラリがあるディレクトリへ ActiveTcl のライブラリをコピー
  2. ActiveTcl のライブラリへのパスを追加する
おすすめは後者です。

ActiveTcl のライブラリを Ruby/Tk のライブラリがあるディレクトリへコピー

利点:簡単(ファイルをコピーするだけ)
欠点:同じファイルが複数あって無駄(アップグレードとかめんどうになる)

以下のようにコピーするだけです。
コピー元:{ActiveTcl のインストール先}\lib\teapot\package\win32-x86_64\lib 内の全て
コピー先:{ruby のインストール先}\lib\tcltk

ActiveTcl のライブラリへのパスを追加する

利点:ファイルをコピーしなくていい
欠点:ソース直しが必要(やる内容は設定ファイルの編集みたいなもんにすぎないけど……)

編集するファイルは、以下 2 つのどちらか。
  • {ruby のインストール先}\lib\ruby\2.0.0\tkextlib\setup.rb
  • {ruby のインストール先}\lib\ruby\2.0.0\tkextlib\{ほにゃらら}\setup.rb
ほにゃららの部分は、例えば jpeg などの画像系の拡張ライブラリのみ適用する場合は
tkimg が入り、以下のようになります。
{ruby のインストール先}\lib\ruby\2.0.0\tkextlib\tkimg\setup.rb

ActiveTcl のライブラリには画像系以外にも色々含まれているので、前者を編集すればいいと思います。
#
#  setup.rb   --   setup script before using Tk extension libraries
#
#    If you need some setup operations for Tk extensions (for example,
#    modify the dynamic library path) required, please write the setup
#    operations in this file. This file is required at the last of
#    "require 'tk'".
#
dir = '{ActiveTcl のインストール先}\lib\teapot\package\win32-x86_64\lib'
TkPackage.add_path(File.expand_path(dir))

パス部分は環境に合わせて適宜読み替えてください。
以下のプログラムを実行してエラーメッセージがでなければ OK です。
require "tk"
require "tkextlib/tkimg/jpeg"
パスがおかしいと、以下のようなメッセージがでます。
C:/ruby/lib/ruby/2.0.0/tk/package.rb:86:in `rescue in require': TkPackage can'tfind package img::jpeg (RuntimeError)
        from C:/ruby/lib/ruby/2.0.0/tk/package.rb:83:in `require'
        from C:/ruby/lib/ruby/2.0.0/tkextlib/tkimg/jpeg.rb:14:in `'
        from C:/ruby/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:53:in `require'
        from C:/ruby/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:53:in `require'
        from test.rb:2:in `
'
2014/01/02 | カテゴリ:Ruby | トラックバック(1) | コメント(0)
外部リンク

カンパのお願い
公開しているソフトウェアはフリーウェアなので無料でご利用いただけます。 気に入ってくださった方は、Amazon でお買い物をする際に下記のリンクを経由して頂ければ励みになります。

検索BOX・タグ一覧