[僕] ruby アーカイブ

僕ト云フ事

たろマークはてなブックマーク

トップ > ruby

2011年02月26日

[citrus][ruby]ruby 1.8 の正規表現でバイト列じゃなくて文字列でマッチする

mobitaro のバックエンドに使い始めた Citrus で、IRC に貼られた URL にあるタイトルを表示する機能があるんですが、woremacx さんから、長いタイトルが変なところで区切られてるという指摘を受けて見てみた。

たとえばこんな感じ。

Ruby 1.9 で日本語(マルチバイト)の文字列を扱�... [text/html; charset=euc-jp]

結論から言うと plugins/http/default.rb の 89 行目、正規表現で60文字までマッチさせて ... をくっつけてるところを u フラグ立てるようにしたら解決。


                if title.size > 70
                        title = title[/.{0,60}/u] + "..."
                end

ruby 1.8系の正規表現は $KCODE の値に従うか、オプションをつけることで文字コードを指定できるみたい。

リテラル/正規表現リテラル

Ruby は日本語化されているので、$KCODE の値に従って正 規表現中の日本語文字を正しく扱います。$KCODE = "n" の場合、日本 語文字を一切認識せずにバイト列として扱います。これはデフォルトの動作で す。

オプションとして n, e, s, u のいずれかを指定す ることで正規表現の文字コードを $KCODE の値に関係なく 個々の正規表現リテラルに指定することもできます。

あと、この問題を追及してるときに、String オブジェクトに to_u8 ってメソッドが生えててなにこれ、と思ったら、lib/citrus/utils.rb にあると、woremacx さんに教えてもらった。オープンクラスで再定義、なるほどー。

2011年02月20日

[irc][ruby]Citrus で twitter の URL が貼られたときに tweet の内容を表示する plugin

irc.lazy-people.org とかに居る mobitaro のバックエンドは chokan だったんですが、twitter の url が貼られたときに、中身を表示してくれという feedback があって、せっかくだからと Citrus に移行した。

だいぶ if 文まみれだけど、とりあえずは動くということで。

2010年07月14日

[coach][iphone][ruby][twitter]iQuestioner がアップデートされました!

忙しくしているうちにすこし間が開いてしまいましたが、皆様いかがお過ごしでしょうか。
最近仕事で関わってた iPhone アプリで iQuestioner という、タッチする度にランダムに問いかけを投げてくれるアプリがあるんですが、今日 twitter 機能を搭載してアップデートされました!

質問に対して答えると #iQuestioner に投稿される仕組みです。
そこで、通勤時間を利用して #iQuestioner にボットを投入しました。

iquestioner.png

iQuestioner に時折現れる、悩み多き「彼」と思わず一言いってしまう「犬」です。
一カ国語につき約60個の台詞 x 日英中の三カ国語で180個 + 自分が勝手に付け足した台詞がいくつかをランダムに1日2回くらい掛け合います。

そしてソースはこんな感じ。ruby 1.9 対策を入れたけど動かしてるサーバは 1.8 系なので意味ないです。

ネームスペース考えて区切ってたつもりが途中からこんがらがってますね >_<
Lazy さんにつけてた自動フォロー返しも搭載してるので、フォローしてね! (そして放置してる Lazy さんごめんなさい >_<)

#iQuestioner で他の人の答えとか見る際に、ちょっとした楽しみになっていただければ幸いです!
ちなみに @iQuestioner はボットじゃないです。中の人は僕でもないです。

あと iQuertioner の回答機能は twitter のアカウントを持ってない人でもローカルに自分の返事を保存しておけるので、以前見た質問がまた出たときは、是非「自分は前にどう答えたんだっけ?」と振り返りに使えますよ!

2009年11月28日

[ruby]クラス名と名前空間かぶるとダメ?

Foo::Bar というクラスのクラスメソッドを Fuga::Foo のメソッドの中で使おうとしたら、Fuga::Foo::Bar なんてクラス無いよと怒られたのでメモ。

追記

IRC で lyokato さんが答えを教えてくれました。

lyokato: ::Foo::Barにしたら呼べるよ!
module Fuga
  class Foo
    def hogera()
      p ::Foo::Bar.test # 頭に :: をつける
      'Fuga::Foo.hogera'
    end
  end
end
 
foo = Fuga::Foo.new
p foo.hogera

これで上手く行きました。
実行結果

"Foo::Bar.test"
"Fuga::Foo.hogera"

どうも呼び出したコンテキストの階層から探しに行って、Fuga::Foo に Foo がマッチしちゃうらしい。頭に :: つけるとトップレベルとして認識されるのね。

元の疑問

環境

  • Mac OS X 10.5.8
  • ruby 1.9.1p129 (2009-05-12 revision 23412) [i386-darwin9]

test というクラスメソッドを持った、Foo::Bar と言うクラスを作ります。

module Foo
  class Bar
    def self.test()
      'Foo::Bar.test'
    end
  end
end

Foo::Bar を Fuga::Foo の hogera で使おうとします。

module Fuga
  class Foo
    def hogera()
      p Foo::Bar.test
      'Fuga::Foo.hogera'
    end
  end
end
 
foo = Fuga::Foo.new
p foo.hogera

すると NameError が >_<

hoge.rb:12:in `hogera': uninitialized constant Fuga::Foo::Bar (NameError)
        from hoge.rb:19:in `
'

でも、クラス名を変えてあげると大丈夫。

module Fuga
  class Awawa
    def hogera()
      p Foo::Bar.test
      'Fuga::Awawa.hogera'
    end
  end
end
 
awawa = Fuga::Awawa.new
p awawa.hogera

実行結果

"Foo::Bar.test"
"Fuga::Awawa.hogera"

なんでだろ。まだ、よくわかってないですね。
あと、やたら名前空間区切りたくなるんだけど、おかしいのかも。作ろうとしてるの、module じゃないからなぁ。

2009年10月26日

[irc][lazy-people][ruby][twitter]IRC と twitter の橋渡しをする lazy さんを作りました

lazy_san_iphone.png lazy people のマスコット、lazy さんの twitter ボットを作りました。今後はイベントごとがあるときはこっちにも通知していこうと思います。
また、twitter で連絡したい人は @lazy_san にもリプライすると良いと思いますよ。

@lazysan は関係ない人ですw)

@lazy_san に reply すると irc.lazy-people.org 上の #project にいる irc bot, lazy_san が IRC 内に通知してくれます。

また、IRC 上の lazy_san に話しかけると twitter 上の @lazy_san が発言します。

09:25 d**y: lazy_san: オーハーヨーーーウィ
09:25 lazy_san: d**y: lazy_san: オーハーヨーーーウィ

lazy_san.png

あとはフォローしてくれたら自動でフォロー返します。お気軽にフォローオ願いします。

ソースはここ。前回の thanksbot と同じディレクトリにいます。

前回書いた thanksbot にもフックするためにまた ruby で書きました。というか、ruby の練習台ですw
あー、thanksbot のプロセス殺して lazy_san 側で呼びかけられ方で振り分けても良いなぁ。でも nick 一覧にないと補完されなくて面倒か。

個人的には thread に触れたことがないので、こんなんで良いのかどうか気になります。

#!/usr/bin/env ruby
# encoding: utf-8
 
$LOAD_PATH << "lib"
 
require 'rubygems'
require 'net/irc'
require 'observer'
require 'lazysan'
require 'yaml'
 
class LazySan::IRC < Net::IRC::Client
 
  def initialize(config)
    @channel = config[:irc][:opts][:channel]
 
    @lazysan = LazySan::Twitter.new(config[:twitter][:user], config[:twitter][:pass])
 
    super(
      config[:irc][:host],
      config[:irc][:port],
      config[:irc][:opts]
    )
  end
 
  def on_rpl_welcome(m)
    post JOIN, @channel
    run_observe_twitter()
  end
 
  def run_observe_twitter()
    @message_thread = Thread.new do
      loop do
        begin
          @lazysan.auto_follow
          @lazysan.replies.each {|status|
            post NOTICE, @channel, "@#{status['user']['screen_name']}: #{status['text']}"
          }
        rescue
          # TODO: Net::IRC の log
        end
        sleep 300
      end
    end
  end
 
  def on_privmsg(m)
    if match = m[1].match(/^lazy_san:\s*(.*)/)
      begin
        @lazysan.update(match[1])
        post NOTICE, @channel, "#{m.prefix.nick}: #{match[0]}"
      rescue
        post NOTICE, @channel, "投稿ミスった >_<"
      end
    end
  end
 
end
 
config = YAML.load_file('lazysan.yaml')
 
lazy_san = LazySan::IRC.new(config)
 
lazy_san.start

クラス構成が LazySan::IRC と LazySan::Twitter とあって、LazySan::IRC が LazySan::Twitter に依存してるのも少し変な気がする。

プログラミング言語 Ruby
まつもと ゆきひろ David Flanagan
オライリージャパン
売り上げランキング: 33589
おすすめ度の平均: 4.0
5 最も信頼できるRubyの本
5 基本書にふさわしい本
5 rubyマスターになるために
3 鬱にされる鬱然たるRuby教科書
2 For Rubist

2009年10月12日

[irc][lazy-people][ruby]irc.lazy-people.org#project に thanksbot を復帰させました。

少し間が開いてしまいましたが、irc.lazy-people.org#project にありがとうを伝える thanksbot を放流しました。
この bot に対してありがとうを伝えると http://lazy-people.org/#ありがとう新着順 の一覧に載ります。まぁ、単純なボットですね。

このチャンネルには元々 thanksbot がいたのですが、lazy-people.org Xen 化作戦失敗以降復帰させていなかったのでした。
旧 thanksbot は mojunc という tomyhero 製 Web API を使っていたのですが、これを復帰させるのがめんどうだったので Wedata を使うことにしました。サーセン >_<
Wedata の使い方はこれで良いのかも謎w

そして、せっかくだからと覚え立ての ruby を使って書くことにしました。
IRC の bot 化には Net::IRC::Client を使い、Wedata への投稿には、こちらのモジュールを使わせていただきました。オリジナルの wedata.rb は、JsonParser に依存していたのですが、gem でインストールできる JSON を使うように少し修正しています。(修正したコード

新規追加しかしないから wedata.rb は大げさだったかも。

#!/usr/bin/env ruby
# encoding: utf-8
 
$LOAD_PATH << "lib"
 
require 'rubygems'
require 'net/irc'
require 'wedata'
require 'observer'
require 'yaml'
 
require 'pp'
 
thanks_config = YAML.load_file('config.yaml')
 
class ThanksBot < Net::IRC::Client
  include Observable
 
 
  def initialize(*args)
    p args
    @channel = args[2]
    args.delete_at 2
    super
  end
 
  def on_rpl_welcome(m)
    post JOIN, @channel
  end
 
  def on_privmsg(m)
    if match = m[1].match(/^thanksbot:\s*(.*)/)
      changed
      notify_observers('', match[0])
      post NOTICE, m[0], "#{m.prefix.nick}: #{match[0]}"
    end
  end
end
 
class ThanksDB < WedataDatabase
  def update(name, message)
    create_item(name, { 'message' => message })
  end
end
 
thanksbot = ThanksBot.new(thanks_config['irc']['host'], thanks_config['irc']['port'], thanks_config['irc']['channel'],thanks_config['irc']['nicks'])
 
thanksdb = ThanksDB.new('thanks', thanks_config['wedata_api'])
 
thanksbot.add_observer(thanksdb)
thanksbot.start

ソースはここにあります。

Net::IRC::Client を継承した ThankBot と WedataDatabase を継承した ThanksDB は ovserver ライブラリを使って observer パターンで動作をひもづけてます。まつもとゆきひろ コードの世界を読んでいて、これを試して見たかったというのが大きいかもw

たぶんなにげに初めて書いた ruby プログラムのような気がします。
既存のライブラリを組み合わせただけでお手軽でした。ありがとうありがとう!

プログラミング言語 Ruby
まつもと ゆきひろ David Flanagan
オライリージャパン
売り上げランキング: 13443
おすすめ度の平均: 4.0
5 基本書にふさわしい本
5 rubyマスターになるために
3 鬱にされる鬱然たるRuby教科書
2 For Rubist
まつもとゆきひろ コードの世界‾スーパー・プログラマになる14の思考法
まつもとゆきひろ
日経BP出版センター
売り上げランキング: 40925
おすすめ度の平均: 4.0
4 Rubyに導入された思考法
トップ > ruby