ActiveRecordのtransactionでrollbackさせる

今つくってるやつは諸事情でActiveLdap使ってLDAPでもユーザの管理してるんだけど、LDAPRDBの整合性をとるって結構無茶な気がしてきた。というか無茶。
とりあえずLDAPの方にデータ登録失敗したら、RDBのデータもロールバックしなきゃいけないからtransaction使ってごにょごにょやってた。ActiveRecordのsave!はずっとvalidator無視してsaveしてしまうメソッドだと思ってたら全然違った。本読まないで勘でやってるとこうなる。今度からちゃんと読もう。
で、save!メソッドは本当はsaveが失敗したときにRecordNotSavedって例外を投げるものだった。transactionはブロックの中で例外が発生したらロールバックする仕様らしいから使わざる終えないっぽい。
最終的にすごく雑だけど↓みたいな感じのソースになった。

def regist
  begin
    @user = User.new(params[:user])
    @ldap_user = LdapUser.new(params[:ldap_user]);
    User.transaction do
      @user.save!
      @ldap_user.save!
    end
    redirect_to :action => 'finish'
  rescue ActiveRecord::RecordNotSaved
    render :action => 'confirm'
  rescue ActiveRecord::RecordNotFound
    redirect_to :controller => 'login'
  end
end

あんまり公表できないソースなので色々削ってます。

password等のパラメータをlogファイルに出力しない

ログイン時のパスワードとかログファイルに書かれたら困る時は↓みたいな感じで。

class ApplicationController < ActionController::Base
  filter_parameter_logging :password
end

これでpasswordって名前で値が渡された場合は出力されなくなる。というか [FILTERED]に置き代わる。
ドキュメント読めば分かることなんだけど、ピンポイントでは探しにくいからメモしとく。

携帯電話向けウィルス

親の知人の携帯がウィルスに感染したららしいので色々調べてみた。そういえば携帯ウィルスの話題なんて触れたことなかった。あんまり人の不幸からこういうこと考えるのよくないかもしれないけど、いい機会だ。

でもまぁ、結局はWikipediaに頼るわけです。ということで→携帯電話ウイルス - Wikipedia

そこから調べられるのはCabirってウィルス。これはSymbian OSってのを狙ったものらしい。ちなみにBlue Tooth経由で感染します。・・・恐ろしい。で、最近まで国内ではメーカ毎にOSが違ったらしいけど、最近はそうでもなくなってきたそうです。WikipediaSymbian OSのページから引用すると、

日本では富士通(F)と三菱電機(D)、シャープ(SH)とソニー・エリクソン・モバイルコミュニケーションズ(SO)がNTTドコモ向けFOMA携帯電話に使用している。ただしこれらFOMASymbian端末は「MOAP」と呼ばれるクローズドなユーザインタフェースを採用しており、サードパーティが自由にソフト開発を行うことができない。モトローラM1000は例外で、UIQインタフェースを採用しており、サードパーティ向けにAPIが公開されている。ボーダフォンからは、S60ユーザインタフェースを採用したノキア702NK702NK IIと804NKが、ソフトバンクモバイルに移行後にSoftBank 705NKSoftBank X01NK(法人向けE61)が、ノキアジャパンよりSIMフリー機であるNokia 6630STD日本版及びE61STD日本版が発売されている。

だそうです。
ただ、日本の会社も携帯電話に関してはウィルスに全く無防備にしてるってわけではなく、きちんと対策もしているようです。McAfeeとドコモの共同開発で、ウィルススキャンって機能が901iから搭載されているとのことです。

そもそも結構最近までは国内ではメーカー毎にOSとかが違ってたわけだから、あまりそういう心配はなかったわけで、最近になって共通のOSが使用されるようになってこういう問題が浮上してきたってことになるんですかね。CabirがBlue Tooth経由で感染ってあたりが恐ろしすぎるんですが・・・。
今回の調査は感染した方の携帯がドコモの端末(機種は不明)だったので、ドコモの端末向けの情報に偏りました。何か面白いので引き続き調査してまとめていこうと思います。

同一テーブルのhabtm

SNSで友人関係を表す場合とかに使いました。多分あんまりないケースだと思います。
こんな感じでてきとーにやったらできました。問題ないのかどうかちょっと心配。

class User < ActiveRecord::Base
  has_and_belongs_to_many :friends, :class_name => 'User', :join_table => 'friends',
                          :foreign_key => 'user_id', :association_foreign_key => 'friend_id'
end

あとは

@user = User.find(1)
@user.friends

こんな感じです。
↓は発行されたSQL。これ見る限り大丈夫っぽい。・・・多分。

SELECT * FROM users INNER JOIN friends ON users.id = friends.friend_id WHERE (friends.user_id = 1 )

リニューアルしたmixiのカスタマイズが熱い

※2007/10/5更新 背景色がちゃんと適用されないのを修正。
4か月ぶりぐらいのブログ更新。最近CSS脳です、こんな時間にこんばんは。

リニューアル後のmixiを2カラム/750px幅化するユーザースタイルシートを書いてみた : akiyan.com
リニューアルを確認した瞬間にやろうと思ったけど、もう既にささっとやってしまった方がおられたのでそれを参考に自分用にカスタマイズ。滅多にしないトラックバックとかもしてみる。実は初めてかもしれない。

個人的には3カラムでも問題なかったので、それはそのまま維持しつつ広告を徹底的に非表示にしてみた。というかmixiニュースとか人気キーワードとか地味に楽しみなので削られると困る。広告に関してはまだ他のページに漏れがあるかも。
あと白が眩しかったから灰色気味にしたのと、トップの最新情報一つ一つに枠線があった方が見やすいって意見があったからそれを反映。確かに見やすい。
最新アルバム、最新ミュージック、自分の最新情報は見ないから非表示にした。あとmiklyとかはいらないからそれも削除。

比較画像

比較は以下の通り。3カラムながらもずいぶんすっきりしたと思う。

変更前 変更後
f:id:gangubako:20071004051118p:image f:id:gangubako:20071004051029p:image

CSS

@namespace url(http://www.w3.org/1999/xhtml);

@-moz-document domain("mixi.jp") {

/* 白があまりにも眩しいのでちょっと灰色気味に */
body { background-color: #f8f8f8 !important; }

/* 最新情報に枠線をつける */
#bodyContents div.contents {
    border: solid #aaaaaa 0px;
    border-width: 0px 1px 1px 1px;
}

/* ロゴ非表示 */
h1 { display:none; }

/* ヘッダの背景を透過色に */
#headerArea { background: transparent !important; }

/* ヘッダの高さをautoに */
#headerArea { height: auto !important; }

/* 検索フォーム非表示 */
div.searchForm01{ display: none; }

/* 「最新情報」ヘッダの非表示 */
#mymixiUpdate div.heading01 { display: none; }

/* 最新アルバム非表示 */
#newAlbum { display: none; }

/* 最新ミュージック非表示 */
#newPlaylist { display: none; }

/* 自分の最新情報非表示 */
#myUpdate { display: none; }

/* 広告バナー非表示 */
*.adBanner { display: none !important; }
#adBanner { display: none !important; }

/* mixiニュース下の広告非表示・ボーダーを自然に */
*.prContents { display: none; }
#mixiNewsArea #mixiNews { background: none !important; }
#mixiNewsArea #mixiNews p.moreLink01 { border-bottom: 1px solid #f6a838 !important; }

/* 日記ページ下の広告非表示 */
*.diaryBottomAd { display: none; }

/* 足あとページ縦バナー広告非表示 */
#footprintjack { display: none; }
#footprintjack02 { display: none; }

/* PR企画非表示 */
#prSepecial { display: none; }

/* mikly非表示 */
#miklyContents { display: none; }

/* プロフィール写真下「mixiプレミアムサービスのご案内」非表示 */
#myProfile p.statusIcon { display: none }

}

感想

自分で一からCSS書くより、人様が作ったページに自分が見やすいようにスタイル適用する方が楽しかった。
多分環境依存とか考えてないからもあるんだろうけど、何にしても自分がカスタマイズ好きなのかもしれない。

HikiのFlickrプラグインを書いてみた

使い方の説明が不親切だったので書き直しました。あとバージョンアップもしたのですが、ファイルが複数になったので公開できる場所ができたら最新版を公開します。

{{ simple_flickr photo_id, [:square|:thumbnail|:small|:medium|:large|:original], [true|false] }}

引数の1つ目(photo_id)

Flickrのphoto idで、Flickrの写真固有のページのURLの最後の部分がそれに当たる。

引数の2つ目(size)

表示するときの画像のサイズ。デフォルト値は :medium になっている。以下のサイズが指定できる。

:square or :s
画像を正方形に小さく表示(75x75)
:thumbnail or :t
サムネイル表示。最長の辺が100px
:small or :m
最長の辺が240px
:medium
最長の辺が500px
:large or :b
最長の辺が1024px(オリジナルのサイズが大きい画像のみで有効)
:original or :o
オリジナルの画像サイズ、形式で表示。

みたいな感じで使う。まだ要望があれば機能拡張する予定。

3つ目の引数(link_to_flickr)

Flickrの写真固有のページにリンクを張るかどうか。デフォルト値は true になっている。

以下ソース

require 'xmlrpc/client'
require 'rexml/document'

def simple_flickr photo_id, size = :medium, link_to_flickr = true
  api_key = @options['flickr_api_key']

  server = XMLRPC::Client.new('api.flickr.com', '/services/xmlrpc')
  res =  server.call('flickr.photos.getInfo', :api_key => api_key, :photo_id => photo_id.to_s)
  xml = REXML::Document.new(res)
  size = size.to_sym
  sizes = {
    :square => '_s', :s => '_s',
    :thumbnail => '_t', :t => '_t',
    :small => '_m', :m => '_m',
    :medium => '',
    :large => '_b', :b => '_b',
    :original => '_o', :o => '_o'
  }
  a = xml.root.attributes
  a_tag = '<a href="' + xml.elements['photo/urls/url'].text + '" target="_blank">'
  img_tag = %Q(<img src="http://farm#{a['farm']}.static.flickr.com/#{a['server']}/#{a['id']}_#{a['secret']}#{sizes[size]}.jpg">)
  if link_to_flickr
    a_tag + img_tag + '</a>'
  else
    img_tag
  end
end