ウェブサービスを作っています。

ruby

MySQL の文字列で表記揺れを吸収しない

MySQL で、データベース・テーブル・カラムなどに collate = utf8_unicode_ci を指定すると、大文字・小文字・全角・半角・ひらがな・カタカナなどの表記揺れが吸収されます。 たとえば、「たろう」と「タロウ」の検索結果が同じになります。 参考: mysqlのc…

Delayed::Job のリトライ速度を調整する

Delayed::Job では、例外が発生した場合、 5 秒 + リトライ回数 ** 4秒経過した後にリトライしてくれますが、これを変更する方法です。 Delayed::Job のバージョンは、2.1.4 です。 やり方は簡単で、ジョブのクラスに、リトライ時刻を返す reschedule_at メ…

Mechanize で送信したデータが反映されないときがある

あけましておめでとうございます。Mechanize 1.0.0 のお話です。 example.com?xx=yy のようにパラメータのついた URL のページから、action 属性が空のフォーム <form action=""> を送信すると、パラメータ無しの URL (example.com) に送信されてしまいます。 agent = Mechan</form>…

MobileAdsense プラグインをリリース

携帯向け AdSense を簡単に設定できる Rails プラグイン MobileAdsense を作りました。 milk1000cc/mobile_adsense · GitHub このプラグインをインストールして、ビューで <%= mobile_adsense :client => 'pub-1234567890' %> のように書くだけで、携帯向け…

CRLF と LF が混ざった CSV ファイルを FasterCSV でパースすると FasterCSV::MalformedCSVError が発生する

FasterCSV.parse %!"123","4\n56"\r\n! # => FasterCSV::MalformedCSVError: FasterCSV::MalformedCSVError 改行コードを統一すれば OK FasterCSV.parse %!"123","4\n56"\r\n!.gsub(/\r\n?/, "\n") # => [["123", "4\n56"]]

Capistrano のレシピを Ruby から実行する

たとえば $ cap delayed_job:restart を ruby で実行する場合は、 require 'capistrano/cli' Capistrano::CLI.parse(['delayed_job:restart']).execute! でできました。 Capistrano のソース (capistrano-2.5.19/lib/capistrano/cli/execute.rb 14 行目あた…

Pacecar が便利

Pacecar とは 便利な named_scope のモジュール集です。 Paperclip, Shoulda, Factory Girl, Clearance など、素晴らしいライブラリを多数開発されている thoughtbot 製。 class SomeModel < ActiveRecord::Base include Pacecar end だけで、『表示可能で投…

rake タスクで発生した例外を Exceptional に通知する

Exceptional.rescue_and_reraise で囲えば OK。 desc 'foo' task :bar => :environment do Exceptional.rescue_and_reraise { ... } end 開発環境では捕捉されて欲しくないので、Exceptional.rescue ではなく Exceptional.rescue_and_reraise を使っています…

ActiveSupport の ClassInheritableAttributes に関して

以下、Ruby 1.8 での話です。 ActiveSupport の機能で ClassInheritableAttributes というものがあります。 これは、継承するクラス変数のようなものです。 クラス変数の問題点 クラス変数は、親クラスに同名のものが存在する場合、子クラスでの変更が親クラ…

role_requirement を導入すると render_optional_error_file がオーバーライドされてしまう

ステータスコード 404 や 500 でも「You don't have access here.」とか出てしまうので、Rails.root/lib/role_requirement_system.rb を修正。 render_optional_error_file オーバーライド部分をコメントアウト # def render_optional_error_file(status) # …

似たようなレイアウトを DRY に記述する

A と B というレイアウトがあって、どちらもほとんど同じレイアウトだけれども、微妙にいろんな箇所が違うという場合にどうするか考えてみました。 まず、骨格となる app/views/layouts/base.html.erb というファイルを作ります。ここには、A・B の共通部分…

role_requirement で、一部のコントローラだけ権限を不要とする

restful_authentication プラグインに権限管理機能を追加する role_requirement というプラグインがあります。 rolerequirement - Clean role-based security for restful_authentication (or acts_as_authenticated) - Google Project Hosting Ruby on Rail…

Nested Attributes の _delete カラムが非推奨になっている

Nested Attributes でデータを削除するためには _delete カラムを使うべきだった気がするのですが、いつの間にか非推奨になっていました。 以下のメッセージが、ログに吐かれます (Rails 2.3.5)。 DEPRECATION WARNING: _delete is deprecated in nested att…

HTTPClient の HTTP::Message::escape_query がちょっと便利かもしれない

require 'rubygems' require 'httpclient' HTTP::Message.escape_query(:a => 'あ', :b => 'foo') # => "b=foo&a=%E3%81%82"

EventMachine によるクローラ実装例

グローバルな並列リクエスト数と、ホスト毎の並列リクエスト数を考慮した試作版です。 もう少し改善出来そうな気がします。 require 'rubygems' require 'em-http' require 'addressable/uri' PARALLEL_REQUEST_NUM = 50 PARALLEL_REQUEST_PER_HOST = 2 uris…

Sinatra でとりあえず logging

require 'rubygems' require 'sinatra' log = File.new(File.expand_path("log/#{ Sinatra::Application.environment }.log", File.dirname(__FILE__)), 'a') STDOUT.reopen(log) STDERR.reopen(log) ..(main code).. もっといい方法がありそうな...

JIT コンパイルを無効にする

google-appengine gem (v0.0.6) を使って GAE + JRuby アプリを作っていると、JIT コンパイルのせいでよくわからないエラーになることがあります。 そういうときに JIT コンパイルを無効にする方法です。 config.ru に追記するだけ。 AppEngine::Rack.app.sy…

メモリリークを起こすジョブを DelayedJob で実行する

1 ジョブごとに worker を終了させて god で再度起動させる、あまり良くない方法です。 ジョブ。グローバル変数 $exit を true にすると、job から worker を終了させられます。 class HogeJob def perform .. (leaking process) .. $exit = true end end de…

Ruby で Task Queue

GAE SDK (Java) 1.2.5 から、Task Queue がサポートされて、appengine-apis (0.0.9) にも早速実装されているようなので試してみました。 taskqueue という適当なタスク追加アプリケーションを sinatra で作ってみます。 ローカルでのみ確認しています。 $ mk…

URI Encode と Punycode の共存

http://日本語.jp/カ/ひ?a=漢みたいな URL を Ruby で http://xn--wgv71a119e.jp/%E3%82%AB/%E3%81%B2?a=%E6%BC%A2に変換する必要があったので、適当にでっち上げました。 弾さんの記事に感謝。あと、punycode4r っていう gem のおかげです。 とりあえず enc…

Delayed Job で、can't dump anonymous class Class というエラーが発生する

Delayed Job とは何か BackgrounDRb 的な何かです。詳しくはググれば、英語のチュートリアル的なものがいろいろ見つけられると思います。 コンストラクタで複雑なことをしているとエラーになる class CrawlJob def initialize @agent = WWW::Mechanize.new e…

Warbler で簡単 Sinatra アプリ on GAE

JRuby と AppEngine SDK (Java) はインストールされているものとします。 JRuby は、mac なら macports などで導入できます。 SDK はインストールとか不要で、ダウンロードして解凍するだけで使えるので、はじめの一歩を踏み出しましょう。 Downloads - Goog…

ランダムな英数文字列の生成

require 'openssl' [OpenSSL::Random.random_bytes(8)].pack('m').gsub(%r![+/=]!) { rand(10) }.strip

Authlogic を使ったときの RSpec ヘルパー

以下を参考に Clearance 風 (?) に書けるようにしました。 AuthLogic is awesome! - Adventures with Ruby authlogic_helper.rb などとして require すれば、以下のように書けます。 describe HogesController do public_context do describe 'GET index' do…

WebService::Simple の Ruby 版を作りました

ゆーすけべーさんが Perl で作られた WebService::Simple の Ruby 版を作りました。 milk1000cc/web_service_simple · GitHub オリジナルは、こちら。 POX over HTTP のウェブAPIにアクセスするためのモジュール「WebService::Simple」を作ってみた - ゆーす…

トラックバック先の AutoDiscovery

RDF に基づいて、渡されたパーマリンクに対するトラックバック Ping URL を自動検出します。 参考: トラックバック技術仕様書 トラックバック関連の gem ってないんですかね。 Timeout::Error も捕捉しています。 require 'net/http' require 'uri' Net::HTT…

Ubuntu に sqlite3-ruby gem を入れる

sudo aptitude install libsqlite3-dev sudo gem install sqlite3-ruby

Merb をインストール

そろそろ Merb をいじってみようということで、眠いのでインストールと最初の一歩だけやってみました。 こちらを参考に。 $ sudo gem install merb $ sudo gem install merb --development どっちかだけでよかったはず。大量に入ります。 development だと c…

ブログに貼られている Dailymotion 動画の mp4 を簡単にダウンロードするスクリプト

見あたらなかったので、作りました。 Dailymotion 動画が貼られているブログのパーマリンクを渡すと、 javascript:document.write('%3Ca%20href=%22http://www.dailymotion.com/...のような結果が出力されます。 これをコピーして、ブラウザのロケーションバ…

FasterCSV でヘッダを考慮

あけましておめでとうございます。 csv ファイルでは、しばしば 1 行目をカラム説明行として使う場合があります。 FasterCSV では、これを考慮して出力することができるんですね。 require 'rubygems' require 'fastercsv' data = [ { 'ID' => 1, 'name' => …