Rails2.0

2.0になったので、とりあえず試してみました。

まず、素直にgemでアップデートしようとしても、なぜか通りません。
これはMacとWinで試しましたが、どうやら共通。
しばらく調べたところ、どうも先にRails1.2.6を入れないとだめみたいです。
で、とりあえず更新しようと思って

gem install rails --version=1.2.6 --include-dpendencies

とかやったらアウト、依存するActive Recordが見つからないようです。
なら、依存するものいらんわ、とこう変更。

gem install rails --version=1.2.6 --ignore-dpendencies

これで無事Rails1.2.6をゲット、さらに

gem install rails --include-dpendencies

以上、無事にRailsのアップデート完了。
後、gemそのものも最新版にしないとrakeがこけたりします。

ちなみにRails2.0ですが、気になった点。

rake migrate

これが

rake db:migrate

こうしないと完全に通らなくなりました。
入力が増えるだけで、ちょっと不便だなぁ、と思うのですが…
プログラム | comments (13) | trackbacks (0)

Ruby のメモリ管理

普段、Ruby でメモリのことなんて気にする機会はないのですが、今回ちょっと面白かったので。

irbを起動して、こんなスクリプトを書いてみます。

a = 1
ary = []
ary << a #Rubyを知らない方は、配列に a を挿入したと思って下さい
p ary[0] => 1
a = nil
p a => nil
p ary[0] => 1

結果を見てもらうと分かるとおり、ary[0] に a を代入して、a が nil になったとしても、ary[0] の中身は変わらないんですね。
Ruby の実装はどうなっているんでしょう?

a = 1 と書くと、a の参照先を適当に設定して、そこに int クラスの無名オブジェクトを生成。
ary[0] << a と書くと、 a の参照先アドレスが ary[0] に渡されて、a に関わらずその参照を持ち続ける、とか?

CとかJavaっぽく考えると上の考え方が正しいのかな、と思います。
もちろん、ソースを読んだわけでも、ましてRubyのコミッタでもないのでてきとーな事を言っているだけですが。

一方こちらは別のケース。

(1..10).each do |i|
a = i
p a.object_id
end

object_id というのはオブジェクトの実体を示すIDなのですが、上のように定義するとループの一回毎にIDが変わります。

a = nil
(1..10).each do |i|
a = i
p a.object_id
end

一方で、こう書くと a の object_id は常に同じ値になります。
ブロック内で定義した変数はブロックから抜けると無効になるので、外で定義すればずっと保持されるという事ですね。
この場合も、やはり a はポインタっぽい雰囲気に思えるのですが…

求む、識者の意見!
プログラム | comments (27) | trackbacks (0)

group by と having

SQLで group by を使うと、where 句というのは意味をなしません。
理由はSQLの実行順序によるもので、指定しようとしてもエラーになります。

例えば、下のSQLは user_type_id ごとの登録ユーザ数を、 users テーブルから取得します。

select count(*) from users group by user_type_id;

会員種別ごとに、ユーザが何人いるのか調べたい場合ですね。

ここで、users テーブルに active という boolean の列があったとして、これが true のユーザのみが有効な会員だとします。
この有効な会員だけを持ってきたい場合、前述のとおり where 句は使えません。
こんな場合、以下のように having 句を指定します。

select count(*) from users group by user_type_id having active = true;

ただし、これをこのまま通すとエラーになります。
理由はSQLのルールに、having で使ったフィールドは「すべて」 group by 句でも指定しないといけない、というものがあるため。
上のSQLは、こう書けば動きます。

select count(*) from users group by user_type_id, active having active = true;

この時、例えば users に年齢をあらわす age という列があったとして、20代の会員を指定したい場合どうすればいいでしょう。
先ほどの話のとおり、having で指定した場合 group by にも指定が必要なので、以下のようになります。

select count(*) from users group by user_type_id, active, age having active = true and age between 20 and 29;

これを実行すると、group by で年齢によるグルーピングをしているため、20代の会員データが年齢別で表示されてしまいます。
今欲しいのは20代すべての人数の合計なので、これではまずいですね。

こんな場合、サブクエリを使って値を絞ってしまうべきでしょう。

select count(*) from (select * from users where age between 20 and 29) as selected_users group by user_type_id, active having active = true;

あらかじめ20代のユーザだけを取得しておく事により、条件の指定が必要なくなっています。

以上、今の案件でRailsを使っているにも関わらず、find_by_sql を使う事が多かったので、何となく。
プログラム | comments (15) | trackbacks (0)

トータルエクリプス

仕事では使うまいと思っていたのですが…
ついに、Java及びEclipseで仕事をしてしまいました。
しまいました、という言い方は語弊がありますが、何となくJavaは使いたくありませんでした。

で、今回使ってみての感想。
Eclipseは拡張であるRadRailsを使っていたおかげで結構分かり、パッケージ管理はFlexBuilderのおかげで分かり、Javaへの理解はRubyをやったおかげで深まっていた、という。
昔よりJavaらしいJavaのコードが書けるようになった気がします。
多言語に生きると専門性は薄れますが、こういう利点もあるという事ですね。
何かひとつだけできればいいというほど恵まれた環境でもないので、このように相互補完していくのが技術力を高める近道だと思います。

そして、今回JavaがRubyより優れていると感じた点。
それは、設計者の意図をより確実にコーダに伝えられる点です。
伝え方は『クラス/メソッドの構造他で無理やり縛る』方式ですが、多人数環境においては有効ではないかな、と。
とりあえず書けば動くというのは、ある意味怖さを含むと感じました。

大真面目な話の後で何ですが、タイトルは前作のラスボスが強烈すぎて、あまり印象に残っていないロマサガ3のラスボスから。
プログラム | comments (16) | trackbacks (0)

真綿で首を

めちゃくちゃやばいわけではないけど、やばい事は分かっていて…

そう、これは…

夏休みが終わるのに宿題に手をつけていない感覚にも似た…

そんな感じの勤務状況です。
唯一のオアシスはFlex。
面白すぎて、今日もこんな時間になったというわけなのサ。

今週は土曜か日曜どちらかはお休みです。。。
プログラム | comments (5) | trackbacks (0)

赤紙

突然ですが…アルバイト募集!

条件
・HTMLの文書構造を理解し、フルCSS、Valid XHTML1.1で記述できる方。
・弊社が用意するコーディングルールを守れる方(ルール自体は、意識しておけば守れるレベルです)。
・特に、経験者歓迎ですが、未経験者も可。研修がほしければ都合します。
・作業期間は11月〜12月くらい。

今のところこれだけです。
HTMLコーディングなので、ページ単価いくら、という感じで在宅勤務も可。
枚数や納期についても都合可能です。
興味のある方は、私のアドレスなり、メッセンジャを知っている方はそちらなりへどうぞ。

やる気と時間が余っている方、ちょっとお金が稼ぎたい方など、いかがですか?
プログラム | comments (12) | trackbacks (0)

imgタグとキャッシュ

Railsを使って、Ajaxっぽく画面遷移なしで画像をアップロードとか、いかにもファッションとか音楽に詳しそうな事をやってみました。
方法については割と知れているのでスルー、iframeを見えない位置に配置して、そこをtargetとしてアップロードフォームを作ります。

今回の問題は、更新時に画像のサムネイルを更新していたのですが、その時に何故か画像『だけ』が更新されない事。
replace_htmlの仕様とか、rjsの仕様とか色々疑ったのですが、理由はもっと簡単な事。
imgタグで読み込んだ画像が、ブラウザでキャッシュされる事でした。
ブラウザのキャッシュをオフにしてもらう回避策はオシャレピラミッドの底辺なので、別の方法を模索。

以下、長くて鬱陶しいので追記で。
続きを読む>>
プログラム | comments (50) | trackbacks (0)

to_xmlで関連を取得したいとき

本家より。

例えば

users = User.find(:all)

で、User has_many Itemsだとして、to_xmlメソッドで関連しているItemsを含むXMLを出力したい場合。

まず、普通のto_xmlはすごく簡単。

users.to_xml

と書くだけで、xml形式で出力してくれます。
オプションの指定などはこの辺を参照。

本題に戻って、ここにitemsを含めたい場合どうするか。

users.to_xml :include => :items

と、いうわけで:includeをオプション指定可能なようです。
ただ、これ以上深い階層の関連には、残念ながら使えない様子。

Items belongs_to Shopだったとしても、これはできません。

users.to_xml :include => [:items => :shop]

何か、なかなか見つからなかったので、メモ程度に。
プログラム | comments (14) | trackbacks (0)

new LITBox

またまたビジュアル系JavaScript。
今度はlitboxですってよ、奥様。

使い方は簡単。

<a href="#" onclick="new LITBox('href', options); return false;">開け</a>

以上。
hrefに画像などを指定(外部ページもいけるみたいです)して、optionsでオーバレイの指定やサイズ指定などを行います。
lightboxなどがページ読み込み完了時にHTMLを追加しているのに対して、こちらは呼び出し時にオブジェクトを作成します。
なので、読み込み動作は多少軽くなる、かも。

以下、困った事。

・何か高さの指定がおかしい

どうも、サンプルページではうまくいっているのに、ページをスクロールしても最上部にボックスが表示されて困りました。
とりあえずソースを見て、litbox.jsの150行目くらいを改変。

// if(this.d2.offsetHeight > h - 100){
// if(!this.options.top || this.options.top < 0){
// this.d2.style.top = "45px";
// }else{
// this.d2.style.top=parseInt(this.options.top)+'px';
// }
// this.d2.style.height=h-100 + 'px';
// //this.d4.style.height=h-145 + 'px';
// this.d4.style.overflow ='auto';
// } else {
if(!this.options.top || this.options.top < 0){
this.d2.style.top = (arrayPageScroll[1] + ((pagesize[1]-this.d2.offsetHeight)/2))+"px";
}else{
this.d2.style.top=parseInt(this.options.top)+'px';
}
// }

こんな感じでコメントアウト。
乱暴ですが、表示が正しくなったので今回はこれでよし。
とんでもない対処療法ですが、気にしない。

・他のメソッド実行しつつ閉じたい

例えば、litboxで開いたウインドウから何かを入力して、同時に閉じるとか。

litbox.jsを開いて、以下の行を探します。

getWindow: function(){

で、この中に2行ほど追加。

this.d.id = "LB_overlay";
this.d2.id = "LB_window";

そして、閉じる動作のメソッドを記述。

<a href="#" onclick="alert('ウホッ'); Element.remove($('LB_overlay')); Element.remove($('LB_window')); return false;">てすと</a>

litbox自体のremove()というファンクションの中身がただのElement.removeだったので、ID指定でremoveしてしまえ、という思想。

・一部メソッドが動かない

今困っているのがこれ。
ロードと同時に中身を作成しないので、一部のElement系メソッド(prototype.js)が使えません。
こればかりはどうしようもないので、書き方を変えるしかなさそうです。

追記

すいませ〜ん、ボク…嘘ついてまし〜た〜…
単に、私のソースがアホだっただけで、Element系メソッドは普通に使えます。
消したつもりで同じ名前のid指定が残っていて、干渉しまくっていたようです。
と、いうわけでそれらのメソッドも普通に使えるし、結構高機能で軽いので、なかなかオススメ。
プログラム | comments (10) | trackbacks (0)

lightboxのつかいかた

lightbox(正確にはlightbox gone wild)というのは、『画面が暗くなって、写真などが浮き上がって表示される』系のエフェクトを作ってくれるJavaScriptのライブラリ。
似たようなもので、もっと強力なlightwindowというのもありますが、そちらは何故か動作が安定しない(ドメイン直下に置かないと安定しないとか何とか)ので、仕事でこちらを採用してみました。

つかいかた。

prototype.js
lightbox.js
lightbox.css

これらのファイルをここからダウンロード。
次に、忘れずにこれらを読み込みます。
prototypeはlightbox.jsの前に読み込むべき。

<script src="/javascripts/prototype.js" type="text/javascript"></script>
<script src="/javascripts/lightbox.js" type="text/javascript"></script>
<link href="/stylesheets/lightbox.css" media="screen" rel="Stylesheet" type="text/css" />

そして、リンクを作成。

<a class="lbOn" href="http://localhost/">開け</a>

classに"lbOn"を指定したすべてのリンクに、lightboxが適用されます。
これだけで、クリックすると画面が暗くなり、画像などを表示する事ができます。

疑問点

・閉じるときはどーすんの

<a href="#" class="lbAction" rel="deactivate">閉じろ</a>

・他のスクリプトを実行しつつ閉じるときは?

<a href="#" onClick="alert('ウホッ'); valid.deactivate(); return false;">閉じろ</a>

なぜvalid何て名前のインスタンスがlightboxクラスなのかはともかく…
ソースを見たら、そこ以外でlightboxクラスを作っていないようだったので、指定してみたらうまくいきました。
正直、もう少し何とかならないのかと。

ちなみに、普通に使う分にはlightwindowの方が高機能じゃないかな、と。
お仕事の世界には納期とか色々あるので…
どこぞの社長も、「ビジネスはスピードよね」と仰ってますし。
プログラム | comments (35) | trackbacks (0)