Skip to main content

ログ取得ツール

ActiveRecordのincrementはポンコツか?

SQLではカウンタのincrement/decrementは1つの文で済ますことになっている。

UPDATE table SET counter = counter + 1 WHERE ...

ActiveRecordのモデルにはincrementやdecrementの定義がある。そうか便利だなぁ…??

1.9.3-p545 :021 > Tbl.take.increment!(:counter, 2)
D, [2014-09-04T00:36:32.902849 #73566] DEBUG -- :   Tbl Load (0.1ms)  SELECT "tbls".* FROM "tbls" LIMIT 1
D, [2014-09-04T00:36:32.903201 #73566] DEBUG -- :    (0.0ms)  begin transaction
D, [2014-09-04T00:36:32.904809 #73566] DEBUG -- :   SQL (0.4ms)  UPDATE "tbls" SET "counter" = ?, "updated_at" = ? WHERE "tbls"."id" = 1  [["counter", 10], ["updated_at", 2014-09-03 15:36:32 UTC]]
D, [2014-09-04T00:36:32.914149 #73566] DEBUG -- :    (9.1ms)  commit transaction
 => true

SELECTで読んで、Rubyが足し算して、UPDATEで足した結果を書き出す…こんなのってないぞ。それをORマッパーがincrementと名乗るか普通? 正解は、モデルのクラスメソッドのupdate_countersを使う。これは複数のカウンタの操作が可能。第1引数のオブジェクトIDも複数書けるし、第2引数以降のカラム名も複数書ける。オブジェクトから呼べないのが使いにくいのを除けば、普通のSQLが発行される。まあ↓の例ではIDを求めるのにSELECTは発行されるが、UPDATE自体は普通にDB側で加算されてくれる。

将棋 (2)

長男がついに将棋の必勝法を編み出しました。それがこの初期配置。 shogi_1 これで、じゃんけんに勝って先手を取る。私は基本的には必ずグーを出して先手を与えているので、飛車爆弾で5手で勝ちます。角まで5三を狙っているのはオーバーキルもいいところですね。何度かやって覚えたなと思ったので、試しにチョキを出して私が先手を貰ってみたところ、それだとまだ勝てないようでした。まあでもだいぶ攻め方も受け方も覚えてきたし、そろそろ自陣は普通の配置からやらせてみようかな…まだ早いかな? 王の近くを空けておくのは、それで何度か逃げ場がなくてやられて学習したんですね。

column(1), colrm(1)

join(1)の衝撃いまだ冷めやらぬ中…column(1), colrm(1)っていうコマンドもありますね。 まあこれらの使い方を覚えようとする前にawkを使うでしょうね。しかしもっと凄いのは、これらのコマンドを涼しい顔で使っている人が会社にいること…かな。なんであんたこれを当然のように使ってんだよ、っていうね。

将棋

子どもたちが将棋にハマっています。きっかけは次男がもらった公文の「スタディ将棋」。動ける方向が書いてあったり成ると赤くなったりする。今はもう普通の漢字の駒でも理解できています。少し前にはオセロにもハマってたんですが、片付けがなかなかできなくて母親に取り上げられてしまいました。将棋は今のところ大丈夫なようです。オセロはハンデをつけにくいからな。隅に置いてあげてもなんか違和感があるようで、たいていハンデなしでやってましたが、普通にやって大人が負けることもありました。どうにもオセロは好手と悪手の区別をつけられる気がしなかったな。 まあ将棋にハマっているとは言ってもまだ子供、「8枚落ち(王金歩のみ) vs. 残りの駒を自由に並び替え」対戦でもまだ大人に勝つのは稀ですが、歩も落としたり金を片方だけにしたりすると勝率が上がるようです。長男と次男だと長男のほうが強いな。さすがに次男はまだ幼稚園の子だからね。三男はまだ駒を勝手に持って握ってたり、動かしたり置いたりしてるだけ。そういやオセロもこいつのせいでそこら中に散らかったんだっけ… 平日は私が相手できる時間も限られていますから、一人でできる棋力向上と言えば詰将棋だろうと、試しに子供向けの詰将棋の本を与えてみたところ、毎日研究しているようです。子供向けだからもうちょっと大きい字でひらがな中心に書いてある本だと思ったら、普通に大人向けの言葉を使ってルビを振ってイラストがあるだけでした。語尾を子供向けにゴマカしたって、言い回しは普通に工夫がないから、小学1年生には分からないですよ。盤面も駒の形がなくて文字の向きで判断する必要がある。長男の読み方を見ていると、文章は見ないで盤面だけ見て考えているようです。しかしもう漢字の向きが分かるんですね。今やっている問題はまだ1手詰めでそんなに難しくない。 囲碁もやってみたいらしく、「スタディ囲碁」のチラシを見せてきまたりしますが、私は囲碁のルールわからんのでまだ相手できんのだよなー。

join(1)

SQLのJOINがどう…というエントリが続きましたが、Linuxのコマンドにもjoinがあり、これはテキストファイルでSQLのinner joinに似た操作ができるんです。私はcutは時に毎日のように使い、たまにpasteは使うことがあるけど、joinは使ったことがない。最近この操作が必要になり、一時的にSQLiteに入れてjoinさせるかawkで頑張るか、sortとuniqで2個カウントされたやつを選ぶか、どうするか熟慮した結果、awkのone-linerでしのいだことを思い出します。joinコマンドさえ知ってれば悩むことなんてなかったのに。 どうせ忘れるけどメモしておこう。MacOSにも入ってます。いやー便利な世の中に…いや、どうせ忘れると思うけどね。

川崎0-1愛媛 (天皇杯…こんなかよ)

久々の等々力。平日夜。新丸子から歩いてどうにかキックオフ前に当日券を買い、中に入った! しかし結果はというと「こんななのかよォ…」 今日のゴールチャンスは最後のポストかバーに当たったやつと、ジェシ(?)のヘッド(GK正面)と小林悠(?)のPKアピールくらいか。いずれもゴールには至らなかった。 サッカー(に限らず、スポーツ全般)見に行くと、嫌でも視力の衰えに気付かされますね。選手の背番号もまともに読み取れねえし、オーロラビジョンのメンバー表も漢字が潰れてる。もしかしてフォントの問題? そんなわけないよね。ここまでの人生を裸眼で過ごして来ました。毎日ずーっとモニタを眺めているコンピュータ業界の人としては珍しいと思いますがこの私の目、そろそろヤバいかもしれないな。 赤外線が見えるサイバネアイはいつ実用化されるんだろう。そんなことを思ったクソ暑い等々力の夜でした。

graphがあったぜSequel

Sequelのjoinの戻り値がどう…というエントリを書いてうだうだ言っていたが、graphというメソッドを使えば一件落着? [pyg language=“ruby”] #! /usr/bin/ruby require ‘sequel’ require ‘pp’ DB=Sequel.sqlite DB.create_table :tbl1s do primary_key :id String :value end DB.create_table :tbl2s do primary_key :id String :value2 Integer :tbl1_id end class Tbl1 < Sequel::Model ; end class Tbl2 < Sequel::Model ; end if $0==__FILE__ Tbl1.insert(:value=>“tbl1data1”) # tbl1s.id=>1 Tbl1.insert(:value=>“tbl1data2”) # tbl1s.id=>2 Tbl2.insert(:value2=>“tbl2data1”, :tbl1_id=>2) # tbl2s.id=>1 Tbl2.insert(:value2=>“tbl2data2”, :tbl1_id=>1) # tbl2s.id=>2

## SELECT * FROM tbl1s INNER JOIN tbl2s ON (tbl2s.tbl1_id = tbl1s.id)

t1=Tbl1.join(Tbl2, :tbl1_id=>:id).first pp t1 # Tbl1{:id=>1, :value=>“tbl1data2”, :value2=>“tbl2data1”, :tbl1_id=>2} t2=Tbl1.graph(Tbl2, :tbl1_id=>:id).first pp t2 # Tbl1{:id=>1, :value=>“tbl1data1”, :tbl2s_id=>2, :value2=>“tbl2data2”, :tbl1_id=>1} end [/pyg] 重複するカラム名はTbl1側が普通に使われ、Tbl2側のカラム名は「テーブル名_カラム名」になる。重複しなければそのまま使える。モデルのクラスはTbl1側。joinがこの仕様だったら良かったんだ。 しかしSQL文を見ると、graphメソッドはLEFT OUTER JOINですね。joinメソッドはINNTER JOINですから、当然結果は異なるわけで、joinは両方にデータがなければ出てこず、graphはTbl1にデータがあれば出てくる。 [pyg language=“ruby”] Tbl1.insert(:value=>“tbl1data3”) # tbl1s.id=>3 Tbl1.join(Tbl2, :tbl1_id=>:id).count # 2(INNNER JOIN) Tbl1.graph(TBl2, :tbl1_id=>:id).count # 3(LEFT OUTER JOIN) Tbl1.left_outer_join(Tbl2, :tbl1_id=>:id).count # 3(LEFT OUTER JOIN) [/pyg] これまでの結論:やっぱSequelのjoin()の仕様はおかしい。

Suica死すともSuicaポイントクラブは死なず…

個人的な事情があって、1月にSuicaを解約し、精算しました。精算に手数料がかかるのが忌々しいですよね。今はPasmoで生活しています。 ところでSuica時代に登録していたSuicaポイントクラブ。これは特定の店でSuicaを使うことでポイントを貯めていき、溜まってきたらSuicaにチャージすることができるというサービス。Suicaポイントクラブでチャージの設定をした後で、確か1週間以内に券売機でポイントのチャージの操作をするとポイントがチャージされて使えるようになるという、夢のようなサービスだ。しかしながらSuicaのポイントを貯められる店は少なく、例えばBeckersとかで貯まっていた。私はSuica解約までの間、1度だけポイントを交換したことがある。 このSuicaポイントクラブ、登録したSuicaを全て解約したらSuicaポイントクラブも自動解約かと思いきや、解約の操作をしないとデータが残るんですね。最近Suicaポイントクラブのサイトが攻撃を受けたようで、アナウンスのメールが飛んできました。今はメンテナンス中でログインできないですが、次にログインした暁には、きっと退会の申請をしようと思う。

ActiveRecordとSequel

RubyのORMはいくつかあるが、Railsで使われているActiveRecordが最もメジャーで、その次くらいにSequelがあると認識している。 最近ふとしたことで両方を使ってみた感想。どちらも、テーブル名を複数形(sつき)にしなきゃいけなかったり、いろいろ面倒だった。勝手に変化させないで欲しいんだよねー。おれ、プログラム上で語尾を変化させるのは好きじゃないのよね。-erと-orの違いとか、sつけるのつけないの、esやiesになるの、受け身だからedだとか、haveかhasかhadとかhavenとか、isかareか、theをつけるかつけないかとか、datumかdataかなんて、考えたくないじゃん。ただのシンボルなんだから。 そういう細かいアレがあるにせよ、どちらも割と使えたんだけど、ActiveRecordはDB側のconstraintを指定できず、例えばカジュアルにuniqueをつけたいと思ってもできない。Ruby側でvalidationを書くかインデックスにuniqueをつけるかしなければならなかったりして、今のところSequelのほうが使用感は良い。ActiveRecordがモデルの記述を重点しているのに対し、Sequelはモデルがなくてもかなりイイトコまで働ける感じ。 例えばJoinの書き方に関してはSequelのほうが直感的で分かりやすい。現代においてSQLを使うというのはすなわちJoinを使うということであるようなのだが、Sequelはモデルに何も書かなくてもキーをjoinの引数に指定するだけでjoinできる。ActiveRecordはモデルにリレーション(belongs_toだの何だの)をつけないとjoinできない。そもそもjoinじゃなくてjoinsなんだよな…三人称単数現在…そこでそうするか。SQLではJOINSなんて書けないよ。んなこと言うならおめーはActiveRecordsじゃねえのかッコラー!! ただSequelのjoinは同じカラム名のものがあるときに、間違った(と私が思う)結果が返ってきてしまうことに気づいた。意味的に考えてバグっている気がする。 つまり、こうだ。 [pyg language=“ruby”] #! /usr/bin/ruby require ‘sequel’ require ‘pp’ DB=Sequel.sqlite DB.create_table :tbl1s do primary_key :id String :value end DB.create_table :tbl2s do primary_key :id String :value2 Integer :tbl1_id end class Tbl1 < Sequel::Model ; end class Tbl2 < Sequel::Model ; end if $0==__FILE__ Tbl1.insert(:value=>“tbl1data1”) # tbl1s.id=>1 Tbl1.insert(:value=>“tbl1data2”) # tbl1s.id=>2 Tbl2.insert(:value2=>“tbl2data1”, :tbl1_id=>2) # tbl2s.id=>1 Tbl2.insert(:value2=>“tbl2data2”, :tbl1_id=>1) # tbl2s.id=>2

川崎1-0新潟 (暑い…)

この、勘弁してほしい暑さ。ビールが飛ぶように売れまくる。しかも客席は満員でコンコースの混み方も半端ない。出遅れてゴール裏のコンコースに立って人垣の後ろから見てました。一人観戦。こんなところに子供たちを連れてこなくて良かった。 始球式の寸劇は暑さもあってちょっとダレましたね。市長挨拶はあろうことか映像のみ。何か大事件でもあったのかい? ハーフタイムの西城秀樹は良いんだけど、ホントそろそろフロンターレコールのやり方を教えてあげたほうがいいと思う。毎年そう思ってこれまで生きてきた。 試合を迎える状況としては、ワールドカップ後はいつになく好調な川崎。まあ天皇杯で危うくYSCCに負けそうになったり、アウェイ3連戦では痺れる展開で全て勝ち切って3位につけ、等々力に戻ってきた。川崎サポにとっては長く待ち望んだホームゲーム。 試合の方は危うい場面もありつつの1-0。1-0なんて川崎らしくない勝ち方だけど、試合内容的には決定機を何度か提供していたのでまあ、普段通りの川崎だったかな。新潟の決定力がなかったということだろう。決定機が何度か…と言っても実際枠内シュートはほとんど受けなかったように記憶している。川崎もレナトや小林悠、大久保が1点ずつ決めてても良かったシーンがあったよね。小林悠は決めたかったろう。決めた森谷も含めてほとんどみんな同じ形の決定機に至っていた。あそこが新潟DFの弱点なのか、川崎の狙いとする形なのか。どうだろう。 この試合を前にしたスポーツ紙の記事で大久保が「こういうときに取りこぼすのがフロンターレ」と言っていたので、だいぶ彼も川崎を深く理解してきたじゃねーか、と嬉しく思っていた。そこでこの勝利。さすがに次は油断してもしょうがない!? 次はアウェイ柏戦、ホーム浦和戦と続きます。