| @技術/プログラミング

暇だったので自動で特定のユーザーを延々favし続けるスクリプトを書いた。

ヒトデ君が書いた hitode909/user-stream-receiver - GitHubRuby+User Stream APIで無言リプライに高速返信するbotを作りました - ps aux | grep aquarla を参考にさせてもらった。というかほとんどまるパクリ。またOAuthのところはtily氏の tily/ruby-oauth-cli-twitter - GitHub に全面的に依存している。

User Stremを受診してるのでcronとかの設定なしでネットストーキングしたい相手のことを延々追跡できる。しかも発言があった瞬間に即favする。大変気持ち悪いですね。

しかしUser Streamはときどき調子が悪く、発言を拾い落とすこともある。そんなときは以下のコードを使う。

これでUser Stream経由で取りこぼした発言もfavできる。それぞれ使い方はこんな感じ。

$ ruby favoritter.rb ストーキングしたい相手のユーザー名
$ ruby favstream.rb ストーキングしたい相手のユーザー名

| @技術/プログラミング

ポータルシットをLokkaに置き換えたくていろいろやってる。ポータルシットの過去記事をYAMLでエクスポートし、それをLokkaのDBに取り込む作業をやってる。TDD BootCampに参加したので、テストファーストしながらの作業。RSpecでテストコードを書き、ログが正しくインポートできることを確認する。テスト終了時 after(:all) フックで、取り込んだログを削除してる。コードはこんな感じ。ちなみにLokkaはDataMapperをORMに採用してるので以下はDataMapperでの話。

after(:all) do
  Category.all.destroy
  Entry.all.destroy
end

しかしこれでは AUTO INCREMENT の値がリセットされず、テストを繰り返す度に AUTO INCREMENT の値が増えていってうざかった。

DataMapperの機能で AUTO INCREMENT 値をリセットするのってないのかなと5秒くらい探してみたけど見つからなかったので、SQLを直接実行する方法を採用した。

ちなみにRDBMSに採用してるのはSQLite3。SQLiteでは UPDTE sqlite_sequence SET seq=0 WHERE name='テーブル名'; みたいなコードで AUTO INCREMENT 値を任意の値に設定できるみたい。

最終的な after(:all) フックはこんな感じ。

  after(:all) do
    Category.all.destroy
    Entry.all.destroy
    Entry.repository.adapter.execute('update sqlite_sequence set seq=0 where name="entries";')
  end

テスト実行後にはすべてのデータがデータベースから削除されて、AUTO INCREMENT の値もリセットされる。人畜無害なテストコード万歳。

| @技術/プログラミング

確認ダイアログを出しながらディレクトリやファイルを削除するスクリプトを書いた。大したコード書いてないし逆引きRubyに載ってたコードをまるパクリしてるところもあるけど便利だと思う。

そのディレクトリにあるファイル/ディレクトリ一覧を取得した後、「このファイル/ディレクトリは作られてから何日経っています。削除しますか? (y/n)」というダイアログ(英語)を表示する。y が入力されると削除を行う。地味に使える。

RubyのFileUtilsはすごく便利だと思う。シェルスクリプトでしこしこ書くのがアホらしくなる。RubyがPerlなみにあらゆるuni*x系のサーバーに入るようになったらさぞかし便利だろうと思う。

| @技術/プログラミング

一個前の記事(Rubyがエレガントだって言われるのがわかってきたような気がする | tech.portalshit.net - CakePHP, Rails, JavaScript)をcxxさんに添削してもらったところ、Rubyの方のコードには問題があったらしい。Rubyでは変数を宣言だけして終わりみたいな初期化をしちゃダメだそうで、必ず何かを代入しないといけないらしい。

そういうわけで正しくは、

class Hoge
  def initialize
    @a = ""
  end

  def hoge
    @a = "hogehoge"
  end
end

fuga = Hoge.new
puts fuga.hoge

と書くそうです。

ところでなんで自分は前回、 @a というインスタンス変数を使ったのかがよく分からない。Railsでコードを書いていて、Controllerで定義した変数をViewで使うときにインスタンス変数を使うので、そういう風に思い込んでいるのかな。上のコードでは別にインスタンス変数を使う必要はなくて、

class Hoge
  def initialize
    a = ""
  end

  def hoge
    a = "hogehoge"
  end
end

fuga = Hoge.new
puts fuga.hoge

でも同じ結果を出力しますね。

インスタンス変数と普通の変数の違いが分かってなかったので、たのしいRuby(第2版)を開いて復習してみたところ、以下のような記述があった。(たのしいRuby 第2版 pp.123-124)

@ で始まる変数は インスタンス変数 といいます。ローカル変数とは違って、このメソッドを抜けてもその値は保存されますが、インスタンスごとに違う値を割り当てられる変数です。(たのしいRuby 第2版 pp.123-124)

なるほど! 例えば上のコードを引数つきのものに改造したとしましょう。

class Hoge
  def initialize(b="")
    @a = b
  end

  def hoge
    print @a, "
"
  end
end

fuga = Hoge.new("Fuga")
piyo = Hoge.new("Piyo")

fuga.hoge
piyo.hoge

で、これを実行すると

Fuga
Piyo

と表示される。こんな感じで、一つのクラスから複数のインスタンスを生成するときに使うのがインスタンス変数って理解でオーケーなのかなと思います。

| @技術/プログラミング

昨日の続きのようなもの。LokkaをUbuntu上で動かそうといろいろやってます。passenger入れて、 passenger-install-nginx-module を実行しようとしたらエラーが出た。お前はrootじゃないからnginxインストールできひんわ、みたいなメッセージが出る。sudoったりrootになってインストールしようとすると今度はpassengerなんていうgemはないわ、って怒られる。sudoしたときには.rvm内のgemパッケージではなくシステムのgemパッケージを見ようとするっぽい。またrootになるとRVMではなくシステムのRubyが実行されるので同じくpassengerなんてgemないわ、って怒られる。システムのRubyは1.8.7だし、なるべくなら使いたくない。RVMのRubyを使ってpassenger + nginxな環境作れないのかよ、とググってたら以下のような記事を発見した。

なんと、RVMには rvmsudo というコマンドがあるらしい! 試しに

$ rvmsudo passenger-install-nginx-module

を実行してみたところ、お前はroot権限がないんじゃ〜とエラーが出ていたところも無事通過してnginxをインストールできてしまった。以前、sudoで無理矢理nginxをインストールしたときは、 nginx.conf 内で、

passenger_root /home/morygonzalez/.rvm/gems/ruby-1.9.2-p136/gems/passenger-3.0.2;
passenger_ruby /usr/bin/ruby1.8;

となっていて大変気持ち悪かったし、Passengerも「PassengerとRubyの本体でバージョンの不整合があるだろヴォケ」みたいな警告出してた。それが rvmsudo のおかげで nginx.conf に書き込まれる値も以下の通りとなるので、とりあえずPassenger(RubyGems)とRubyのバージョンが異なるというような問題は回避できる。

passenger_root /home/morygonzalez/.rvm/gems/ruby-1.9.2-p136/gems/passenger-3.0.2;
passenger_ruby /home/morygonzalez/.rvm/wrappers/ruby-1.9.2-p136/ruby;

ただ、なんでか分からないのだけどnginxがうまく動いてくれなくて、無事Webサーバーを起動できてない感じです。

それにしてもRVMは、本当にきもいと思う。readlineとかまで.rvm内にインストールできるできるし、いったい何考えてるんでしょうかね。きもすぎて便利です。

| @技術/プログラミング

RVMを使ってます。RVMで入れたRubyがshebangに #!/usr/bin/env ruby と書いたときに呼び出されて欲しいと思ってます。シェルから

#!/usr/bin/env ruby

puts RUBY_DESCRIPTION

なファイル(hoge.rb)があったとします。これを

$ ruby hoge.rb

とシェルから呼び出したときにはちゃんと

$ ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-darwin10.6.0]

と表示されます。しかしTextMateでRunしたときや、Apacheから同じshebangで呼び出したときには、systemのRubyが呼ばれます。

これ、もう半年くらい解決方法探してる気がする。

TextMateでRunしたときにsystemのRubyが呼ばれるのはともかくとして(テストするときはシェルから呼び出すのでRVMのRubyで実行できる)、Apacheで新しめのRubyを使いたいときはどうすればよいのでしょう。まさかshebangに ~/.rvm/bin/ruby-1.9.2-p136 とか書くんじゃろか。

cxxさんに質問したら RVM: Ruby Version Manager - Installing RVM System Wide というURLを教えてもらった。今日は眠いのでまた今度試す。

| @技術/プログラミング

Ruby 1.9、Rails 3、RSpec 2で開発してる。いままでRubyとRailsになれるのに一杯一杯でテスト駆動開発できてなかったので、きちんとテストファーストでやることにした。

そんで環境を整えてたんだけど、RSpecはRails 3に合わせてVersion 2が出てるみたい。しかも結構変わってる。

$ spec -c spec/*

とかやってもエラーが出る。 which spec すると /usr/bin/spec と出ちゃう。どうやら spec で発動されるのはRSpec 1.3のものみたい。

RSpec 2からはコマンド名が変更されており、テストコードを実行したいときは以下のように書くみたい。

$ rspec -c spec/*

これできちんとテストコードが実行された。かと思いきやFailureが。

Ruby 1.9で動かしてるから、コードの中に日本語を書くときは一行目に

# -*- coding: utf-8 -*-

と書いてテキストエンコーディングを明示してあげないといけない。