Posts Tagged ‘Ruby’

| No Comments | 1月 9th, 2008

 Ruby1.9 は、mail でどうぞ -> Ruby1.9 でメール解析(変なヤバいもんログ内)

Tmailというライブラリを使うと、メールを解析して扱いやすくしてくれます。

Tmailのインストール

# gem install tmail

パース方法

ファイルからパースする

メールがファイルであるならば、Fileクラスのインスタンスを渡してTMailクラスのインスタンスを作る。

receive1.rb

#! /usr/bin/ruby -w
require 'rubygems'
require 'tmail'
 
file = File.open('mail.txt'){|f| f.read}
email = TMail::Mail.load(file)
p 'to: ', email.to
p 'from', email.from

TMail::Mail.load を使ってFileクラスのインスタンスを渡すとそれを解析してくれる。mail.txt で FromとToが以下のようになっていたとすると、それぞれが配列に入る。

From: from_address@ecpplus.net
To: to_address@ecpplus.net

$ ruby receive1.rb
"to: "
["to_address@ecpplus.net"]
"from: "
["from_address@ecpplus.net"]

標準入力からパースする

receive2.rb

#! /usr/bin/ruby -w
require 'rubygems'
require 'tmail'
 
email = TMail::Mail.parse(STDIN.read)
p 'to: ', email.to
p 'from', email.from
$ cat mai.txt|ruby receive2.rb
"to: "
["to_address@ecpplus.net"]
"from: "
["from_address@ecpplus.net"]

添付ファイルを取得する

tmailダウンロードするとサンプルがついているので、それにならう。

receive3.rb

#! /usr/bin/ruby
require 'rubygems'
require 'tmail'
 
def main
  mail = TMail::Mail.parse(STDIN.read)
  mail.to # To: を取得
  mail.from # From: を取得
  idx = 1 # 複数の添付ファイルがあった場合のファイル名にしてる
  mail.parts.each do |m|
    m.base64_decode
    File.open("#{idx}.#{ext(m)}", 'w') {|f|
      f.write m.body
    }
    idx += 1
  end
end
 
CTYPE_TO_EXT = {
  'image/jpeg' => 'jpg',
  'image/gif'  => 'gif',
  'image/png'  => 'png',
  'image/tiff' => 'tiff'
}
 
def ext( mail )
  CTYPE_TO_EXT[mail.content_type] || 'txt'
end
 
main
$ cat mai.txt|ruby receive3.rb

これで、1.jpg, 2.png のようなファイル名で添付ファイル保存されるので、これで何かしたかったら分かるように保存しておけばOK。

メールサーバに来たメールを解析するとき

メールサーバにメールが届いたらそれをトリガーにして エイリアス作って渡してあげます。トリガーのひきかたは、省略。
/etc/aliases に以下のように記述して、 chihaya@ に来たメールを引数で渡すようにします。

chihaya: "|/usr/bin/ruby  /home/chihaya/receive3.rb"

あとは STDIN.read で標準入力を読んで処理すれば大丈夫。解析後のデータを使ってお好きなように。

| No Comments | 1月 2nd, 2008

オブジェクトのプロパティを send メソッドで参照するには、send の引数にプロパティの名前を渡せばいい。

たとえば、以下のようなUserクラスがあったときに send で nameをひっぱって来るには以下のようにする。

class User
  attr_accessor :name, :email
  def initialize(name, email)
    @name = name
    @email = email
  end
end
 
>> user = User.new('chu', 'chu@example.com')
=> #<user:0x2b5764296468 @email="chu@example.com", @name="chu">
>> user.name
=> "chu"
>> user.send('name')
=> "chu"

設定ファイルでフィールド決めて内部で処理するようなときはよく使う。

次に、send を使ってオブジェクトのプロパティに 値を設定したい場合は、 send に引数を二つ渡す。 ruby は プロパティへのアクセスも全てメソッドになってる。

name属性への代入は、 name= というメソッドに引数を渡していることになる。

>> user = User.new(‘chu’, ‘chu@example.com’)
=> #
>> user.send(‘name=’, ‘chu2′)
=> “chu2″
>> user.name
=> “chu2″

send について調べてみたら、以下のようになっていた。第一引数にメソッド名を渡して、そのメソッドに対する引数は可変長の第二引数以降に渡せばいいみたい。

send(name[, args ... ])
send(name[, args ... ]) { .... }
__send__(name[, args ... ])
__send__(name[, args ... ]) { ... }

オブジェクトのメソッド name を、引数に args を渡して呼び出し、メソッドの実行結果を返します。
ブロック付きで呼ばれたときはブロックもそのまま引き渡します。メソッド名 name は文字列かSymbol です。
send が再定義された場合に備えて別名 __send__ も用意されており、ライブラリではこちらを使うべきです。また __send__ は再定義すべきではありません。
send, __send__ は、呼び出し制限 にかかわらず任意のメソッドを呼び出せます。
ruby 1.9 feature: 呼び出し制限がsend, __send__にも影響するようになり、レシーバを指定した呼び出しではprivateメソッドを呼び出せなくなりました。 privateメソッドを呼び出す必要がある場合はinstance_evalを使用してください。

| No Comments | 12月 13th, 2007

gem install mysql もう何回やってるんだって話だけど、つまずいたのでメモ。

–with-mysql-config で mysql_config のコマンドを呼ぶ。MacのPortで入れると、 /opt/local/bin/mysql_config5 というのが入るからこれを指定する。

% sudo gem install mysql -- --with-mysql-config=/opt/local/bin/mysql_config5

こんな感じでやれば無事とおる。

Debian だと、mysql が入っていても mysql_config が無いことがある。libmysqlclient15-dev というパッケージに入ってる。

% sudo apt-get install libmysqlclient15-dev

| No Comments | 8月 30th, 2007

RubyもしくはRailsで配列を扱う時のtips

Rubyのメソッド

each_with_index

eachと同じ感じなんだけど、何番目かっていう数字を一緒に取れる。ループの外で i = 0 と定義して、ループの中で i += 1 とかやらなくておk。ブロックの第一引数が配列の要素で、第二引数が配列のインデックスです。

%w(a b c d).each_with_index do |value, index|
  p value
  p index
end

実行結果

"a"
0
"b"
1
"c"
2
"d"
3

all?

ブロックをとって、各要素に対して条件を指定して、全てが true だったら true を返す。

[1,2,3,4].all? do |value|
  value > 0
end

実行結果

true

any?

ブロックをとって、各要素に対して条件を指定して、1つでも true だったら true を返す。

[1,2,3,4].any? do |value|
  value == 3
end

実行結果

true

-

配列から、特定の物を取り除く時に簡単に使える。例えば、配列をjoinしたいけど、nilは除いてからjoinしたい時とか。

irb(main):021:0> [1,2,nil,4,5,nil] - [nil]
=> [1, 2, 4, 5]

compact

配列から、nilを取り除いた配列を返す。破壊的メソッドは compact!

irb(main):021:0> [1,2,nil,4,5,nil].compact
=> [1, 2, 4, 5]

uniq

配列から重複したものを取り除きたい時。破壊的メソッドは uniq!

irb(main):022:0> [1,1,2,3,4,2,5].uniq
=> [1, 2, 3, 4, 5]

collect (map)

配列の各要素をブロックに渡し、各結果を配列にして返します。破壊的メソッドは collect! 。map と collect は同じ。

irb(main):001:0> [1,2,3,4,5].collect do |i|
irb(main):002:1*   i * 10
irb(main):003:1> end
=> [10, 20, 30, 40, 50]

index

引数の値と一致する最初の位置を返します。

irb(main):004:0> %w(a b c d e).index('c')
=> 2

Railsのメソッド

in_groups_of

引数に個数を取って、その個数ごとの配列を生成して、その配列を返してくれる。半端な部分はnilで埋めてくれる。table組むときとか超便利。日本語むずい。

 [1,2,3,4,5,6,7].in_groups_of(3) do |group|
?> p group
>> end
[1, 2, 3]
[4, 5, 6]
[7, nil, nil]
=> nil

また今度追記するわ。

| No Comments | 7月 16th, 2007

Rubyで Net::HTTPS を使おうとしたら、require ‘net/https’ でエラー。どうやら、 require ‘net/https’ した時に、中で require ‘openssl’ を呼べてないぽい。環境はDebian sarge 。

Rubyをソースから入れたので、zlibのインストール の時のような手順で入れたら入った。

Rubyforge からダウンロードした ruby のソースコードのディレクトリへ移動。ディレクトリ名を ruby-1.8.5 とする。openssl は既にインストール済みだった。以下のようなコマンドでインストール出来た。

$ cd ruby-1.8.5/ext/openssl
$ ruby extconf.rb
$ make
# make install

チェックしてみる。

$ irb
irb(main):001:0> require 'openssl'
=> true

通ってるようだ。

ruby extconf.rb--with-openssl-dir=/usr/local/openssl のような形で指定することも出来るようだが、自動的に見つけてくれた模様。

ちなみに、Ubuntu8.04 の環境だと、初めは libssl-dev が入っていないので、apt で入れてあげましょう。

% sudo apt-get install libssl-dev
download the hurt locker