Hatena::ブログ(Diary)

いとうまさしのカチャカチャTODAY

2010-08-24

bit.lyで短縮URLを作る手順

08:26

f:id:itmsc:20100824082312p:image



f:id:itmsc:20100824082507p:image



  • 「Shorten with bit.ly」と書かれたフォームにURLをペーストします。
  • 「Shorten」ボタンを押します。

f:id:itmsc:20100824082506p:image



  • 「Your link →」というエリアが現れます。その横に短縮URLが表示されます。

f:id:itmsc:20100824082505p:image



  • Twitterで短縮URLを使ってツイートします。
  • しばらくまって http://bit.ly にアクセスします。
  • ページの中段まで下がると、短縮URLをクリックしてくれた人の人数が表示されています。

f:id:itmsc:20100824082857p:image

2010-05-07

background_fuで「あとでやる」処理を書く

| 14:30

railsを使って「あとでやる」処理を実現する方法について

rubyMLに回答をしてみたので、内容をここにも書いておきます。

質問メールは以下の通り。

RubyRailsも初心者なのですが、
現在、Railsで簡単なtwitterbotを作成しています。
Railsで作った設定画面から、投稿間隔の設定を
行い、後で変更できるようにもしたいのですが、
良いやり方がいまいち思いつかず、
困っています。

今のところ、考えているものは以下です。
1、cronで実行
2、backgroundrbで実行
3、タイマーでループ回して処理
  (投稿間隔はDBから取得)

投稿間隔の設定ができるボット作成サイトなどは、
結構あるみたいなので、なんらかの方法でできると
思うのですが、恥ずかしながら、やり方がわからず、
質問させていただきました。できれば簡単な方法
でやりたいと思っています。

僕の回答は以下。

> > 2、backgroundrbで実行
> > 3、タイマーでループ回して処理

background_fu を使って投稿の間隔を設定する方法を大雑把に紹介します。
(タイマーうんぬんはbackground_fuの仕組みがケアしてくれます。)

background_fu は以下な感じでデーモンとして起動させておきます。

ruby script/daemons start

デーモンはjobsテーブルを5秒間隔(設定で変更可能)で
selectします。

処理してよいJobがあれば実行します。
(処理してよい => 未処理 && 開始時刻過ぎてる)

実行する処理はlib/worker以下にクラスを作っておきます。

JobにはWorkerのクラス名、メソッド名、引数、実行開始時刻
を入れておきます。

Job.create!
:worker_class => 実行するWorkerのクラス名,
:worker_method => 実行するWorkerのメソッド名,
:args => メソッドの引数,
:start_at => 実行開始時刻

みたいな感じ。

2010-04-16

buildって何だろう?

| 13:44

ActiveRecordのアソシエーションを扱うメソッドで「build」というのを初めて知りました。

class Group < ActiveRecord::Base
  has_many :users
end

class User < ActiveRecord::Base
  belongs_to :group
end

というアソシエーションがあったときに、

@group.users.build params

みたいな感じで書くことができます。

@group.users << user

みたいなコードは save まで実行されてしまうので、場合によっては build の方がいいかと。

belongs_to についての build なら

@user.group.build params

だけじゃなくて

@user.build_group params

という書き方もできるようです。

参考:

Rails new vs build http://vinhboy.com/blog/2009/01/15/rails-new-vs-build/

2010-04-15

ActionViewとActionControllerでurl_forの挙動が違います

| 21:58

URLを出力するためにつかう「url_for」というメソッドがあります。

root_path, root_url, XXXX_path, XXXX_urlなどroutes.rbで定義したURLを呼び出すメソッドでも内部的に使っています。

このurl_forやXXXX_urlですが、Controllerの中で呼ぶときとViewの中で呼ぶときで挙動が違います。

Viewで呼ぶ時はURLがエスケープされたものが返ってくるのです。

Controllerでは

http://localhost:3000/controller/action?a=1&b=2

となるところがViewだと

http://localhost:3000/controller/action?a=1&amp;b=2

となります。

普通にブラウザを相手にする場合は問題ないですが、

ActionMailerで送信するメールの文面の場合は不具合の素になるので注意が必要です。

url_forの引数に「:escape => false」を渡すとエスケープされずに返ってきます。

2010-02-19

file_columnで受信メールの添付画像を保存する方法

| 16:48

前提

Statusモデルにimageというフィールドがあって、そこがfile_columnを採用している。

メールを受信したら添付ファイルをstatus.imageに格納したい。


(1)file_columnの一部を拡張します。

vendor/plugins/file_column/lib/file_compat.rb

を以下のように変えます。

(- で始まる行が元々のコード、+ ではじまるのが変更後のコードです。)


   module FileCompat # :nodoc:
     def original_filename
-      File.basename(path)
+      @original_filename || File.basename(path)
     end
+
+    def original_filename=(name)
+      @original_filename = name
+    end


(2)StatusMailerというActionMailerを作る

メールを受信するためのクラスです。

中身はこんな感じ。

class StatusMailer < ActionMailer::Base  
  def receive(email)
    Status.parse_mail(email)
  end
end

メールを受信するための.forwardファイルは下記のような感じ。

| RAILS_ROOT/script/runner -e production 'Status.receive(STDIN.read)'

(3)Statusモデルの中に本体を実装

  def self.parse_mail(email)

    # email.to を解析して 対象の status を割り出す。
    status = ....

    # 添付画像を取得する
    if email.multipart?
      email.parts.each do |m|
        if m.main_type == 'image'
          # file_columnへの引き渡し
          status.save_image_from_mail m
          break
        end
      end
    end
    status
  end

  def save_image_from_mail(mail_part)
    # ランダムな文字列に拡張子を付けた形でファイル名を作る
    tmp_filename = Digest::SHA1.hexdigest( rand.to_s ).slice(1..10) + '.' + mail_part.sub_type

    # Tempfileを作って、データを格納する
    tmp = Tempfile::new tmp_filename
    tmp.puts mail_part.body

    # file_columnへの引き渡し準備
    tmp.extend FileColumn::FileCompat
    tmp.original_filename = tmp_filename

    self.image = tmp
    self.save

    # 後片付け
    tmp.close
  end

(4)動作確認

メーラーの適当なメールを.emlとかテキストフォーマットで保存する。

script/consoleを起動

・以下を実行

$ f = open '.emlファイルのパス'
$ StatusMailer.receive(f.read)