2011年9月9日金曜日

Ubuntu10.04でGAE on Python

GAE on Python を Python の勉強がてらやってみようかと。
で、イロイロ踊らされてしまった内容をツラツラと書こうかと。

まず、前提条件としてGAEはPython2.5でないとイカンという有名な話がある。
Ubuntu10.04はPython2.6が標準インストールされている。
根が横着なので、Python2.6でGAEを動かそうと考えた訳で。
結論から言うとちゃんと動きました。App Engine SDK に手を加えることなく動きます。

何が問題だったかと言うと、まず、単純にSDKの最新版をダウンロードして適当なフォルダに解凍した。んでチュートリアルに従ってプロジェクトを作成し実行したら、下記エラーが発生した。

Warning: You are using a Python runtime (2.6) that is more recent than the production runtime environment (2.5). Your application may use features that are not available in the production environment and may not work correctly when deployed to production.
INFO     2011-09-09 08:40:30,324 appengine_rpc.py:159] Server: appengine.google.com
WARNING  2011-09-09 08:40:30,330 datastore_file_stub.py:512] Could not read datastore data from /tmp/dev_appserver.datastore
INFO     2011-09-09 08:40:30,333 rdbms_sqlite.py:58] Connecting to SQLite database '' with file '/tmp/dev_appserver.rdbms'
Traceback (most recent call last):
  File "google_appengine/dev_appserver.py", line 77, in 
    run_file(__file__, globals())
  File "google_appengine/dev_appserver.py", line 73, in run_file
    execfile(script_path, globals_)
  File "/app_path/google_appengine/google/appengine/tools/dev_appserver_main.py", line 689, in 
    sys.exit(main(sys.argv))
  File "/app_path/google_appengine/google/appengine/tools/dev_appserver_main.py", line 653, in main
    default_partition=default_partition)
  File "/app_path/google_appengine/google/appengine/tools/dev_appserver.py", line 4971, in CreateServer
    server = HTTPServerWithScheduler((serve_address, port), handler_class)
  File "/app_path/google_appengine/google/appengine/tools/dev_appserver.py", line 4999, in __init__
    request_handler_class)
  File "/usr/lib/python2.6/SocketServer.py", line 400, in __init__
    self.server_bind()
  File "/usr/lib/python2.6/BaseHTTPServer.py", line 108, in server_bind
    SocketServer.TCPServer.server_bind(self)
  File "/usr/lib/python2.6/SocketServer.py", line 411, in server_bind
    self.socket.bind(self.server_address)
  File "", line 1, in bind
socket.error: [Errno 98] Address already in use

ここでちゃんとエラーを読んでググってればここで終わったのにちゃんと読まなかったため
ぁぁ、やっぱりPython2.5が要るんだなと判断しちゃって、瞑想しちゃいました。
ちなみに、このエラーはAddress already in useと出てて、アドレス使ってますよと言っています。
Tomcatをインストールしていて、それが自動起動しちゃってたため、ポート8080がかぶって起動しなかったのです。
それをPython2.5入れて、環境汚さないようにvirtualenv入れてとかイロイロやったけど、起動するときに
google_appengine/dev_appserver.py -p 8081 /app_path
で、起動しちゃいました。 なんか、どっと疲れた。 これから、ちょっとずつPythonやってなんかサイト作ります。

2011年6月8日水曜日

ubuntu 10.04 で Ruby(環境構築編) その2

だいぶ前に ここで RVM の設定方法を書き込んだが、今ではだいぶ楽になっていた。
ビックリしたのでメモ。

1.事前準備

rvm を動作させるのに必要なものを一式インストールする。
sudo aptitude install git-core curl zlib1g-dev

rvm をセットアップする場所を作成して、移動する。
mkdir ~/.rvm
cd ~/.rvm

2.インストール

以下のコマンドを実行する。
bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
すると、カレントディレクトリに rvm 絡みが一式できてる。(ここでは ~/.rvm 配下)

後は、コンソールに表示されている内容の修正を .bashrc or .bash_histry に加える。
具体的には、
#.bashrc
[ -z "$PS1" ] && return
の欄を
#.bashrc
if [[ -n "$PS1" ]] ; then

  # ... original content that was below the '&& return' line ...
  [ -z "$PS1" ] && return

fi # <= be sure to close the if at the end of the .bashrc.

# This is a good place to source rvm v v v
[[ -s "/home/matsumoto/.rvm/scripts/rvm" ]] && source "/home/matsumoto/.rvm/scripts/rvm"  # This loads RVM into a shell session.
に書き換えるだけ。

書き換え後は、
source .bashrc
で変更を反映させる。



■おまけ

RVM のコマンドリスト(少しだけ)
rvm list インストールされている Ruby を一覧表示
rvm list known rvm でインストール可能なすべてのバージョンを表示
rvm install version 指定されたバージョンの Ruby をインストール
rvm [use] version [--default] 使用する Ruby を選択する。
--defaultを指定すれば、それが常に利用される。
rvm uninstall version 指定したバージョンの Ruby を削除する。
rvm --help 困ったときはヘルプを見るべし!


■最後に

RVM 自体のアンインストール
rvm implode

した後に、RVM_HOME のソース類をゴソッと削除して、.bashrc or .bash_histry を修正する。

かなぁ。

近状

なんか、久しぶりの投稿になる。

身の回りが忙しくブログ書いてる暇がない。
けどネタはいっぱい増えている。
  • ubuntu 10.04 64bit の日本語化
  • ubuntu 10.04 の OpenOffice.org を LibreOffice に変更
  • Play framework for Scala のこと
  • RVM のインストール方法(改)
  • JRuby on Rails のこと
時間見つけて書き込んでいこう。
(いけるかな?)

2011年4月8日金曜日

Rails3 routes

やはり触れることになってしまった routes.rb。これを期に意味不明な部分を理解しよう。
勉強して得られた情報をメモ。

routes.rb にて生成される URL については rake routes コマンドにて確認できる。
記載する出力結果はすべて rake routes にて出力された結果です。


match(path, options={})


route 師弟の基本。アクセス可能な path を指定してやることで、HTTP リクエストを処理できるようになる。
match "foo/bar"
# foo_bar  /foo/bar(.:format) {:controller=>"foo", :action=>"bar"}
path は必ず一つ以上 "/" を入れてやる必要がある。
  • match "foo" => NG
  • match "foo/bar" => :controller=>"foo", :action=>"bar"
  • match "foo/bar/buz" => :controller=>"foo/bar", :action=>"buz"
"/" を複数指定した場合、controller の namespace を表すように解釈される。

以下指定可能オプション。(全部じゃないかも)

:controller
:action
動作させるコントローラとアクションを指定する。
必ずセットで指定する。
path に "/" を入れなくてもこのオプションを指定してやれば解釈されるようになる。
match "foo", :controller=>"foo", :action=>"bar"
# foo  /foo(.:format)  {:controller=>"foo", :action=>"bar"}
:to :controller, :action の短縮形。"#" でコントローラとアクションを区切って記述する。
match "foo", :to=>"foo#bar"
:to の記述自体を短縮する方法もある。
match "foo"=>"foo#bar"
:via HTTP メソッドを付加する。
match "foo/bar", :via=>:get
# foo_bar GET /foo/bar(.:format) {:controller=>"foo", :action=>"bar"}
:as ルート名を指定する。ルート名は form_tag や link_to などで指定できる名前で、その名前に該当する path を生成して form を作成してくれる。
match "foo/bar", :as=>"bar"
# bar GET /foo/bar(.:format) {:controller=>"foo", :action=>"bar"}


get

post

put

delete


match の :via オプションの HTTPHelper メソッド。
指定可能なパラメータは match と同様。なので
get "foo/bar", :via=>:delete
なんていうふざけた記述もちゃんと解釈してくれる。(HTTP メソッドは GET になります)


resource

resources


Rails のルールに従って RESTful 的な URL を自動で生成してくれる有名なメソッド。
単数形の場合は resource を、複数形の場合は resources を利用する。*指定する名前も単数形、複数形を意識して指定してやる。(resource :foo, resources :foos)
二つの違いは一覧出力 URL (scaffold 生成時の index アクション) の有無の違い。

以下指定可能オプション。(全部じゃないかも)
:as ルート名に利用する別名。
resource "foo", :as=>"bar"
#   bar POST   /foo(.:format)      {:action=>"create", :controller=>"foos"}
# new_bar GET    /foo/new(.:format)  {:action=>"new", :controller=>"foos"}
#edit_bar GET    /foo/edit(.:format) {:action=>"edit", :controller=>"foos"}
#       GET    /foo(.:format)      {:action=>"show", :controller=>"foos"}
#       PUT    /foo(.:format)      {:action=>"update", :controller=>"foos"}
#       DELETE /foo(.:format)      {:action=>"destroy", :controller=>"foos"}
:controller 処理するコントローラを指定する。
アクション名は Rails ルールに従う必要がある。
resource "foo", :controller=>"bar"
#   foo POST   /foo(.:format)      {:action=>"create", :controller=>"bar"}
# new_foo GET    /foo/new(.:format)  {:action=>"new", :controller=>"bar"}
#edit_foo GET    /foo/edit(.:format) {:action=>"edit", :controller=>"bar"}
#        GET    /foo(.:format)      {:action=>"show", :controller=>"bar"}
#        PUT    /foo(.:format)      {:action=>"update", :controller=>"bar"}
#        DELETE /foo(.:format)      {:action=>"destroy", :controller=>"bar"}
:path URL を置き換える。
resource "foo", :path=>"b/a"
#   foo POST   /b/a(.:format)  {:action=>"create",:controller=>"foos"}
# new_foo GET    /b/a/new(.:format) {:action=>"new",:controller=>"foos"}
#edit_foo GET    /b/a(.:format)     {:action=>"edit",:controller=>"foos"}
#         GET    /b/a(.:format)     {:action=>"show",:controller=>"foos"}
#         PUT    /b/a(.:format)     {:action=>"update",:controller=>"foos"}
#         DELETE /b/a(.:format)     {:action=>"destroy",:controller=>"foos"}
:only 作成される URL を絞り込む。指定されたアクションのみ URL が生成される。
resources "foo", :only=>["index"]
# foo_index GET /foo(.:format) {:action=>"index", :controller=>"foo"}
:except 作成する URL を削除する。指定されたアクションは URL が生成されない。
こう書けば、:only と同じ結果になる。
resources "foo", :except=>["create","edit","new","show","update","destroy"]
# foo_index GET /foo(.:format) {:action=>"index", :controller=>"foo"}
:module controller に namespace を付加する。
resources "foo", :only=>["index"], :module=>"module"
# foo_index GET /foo(.:format) {:action=>"index", :controller=>"module/foo"}

has_many の関係を定義する場合、block を渡して resources を定義する。

resources "foo" do
  resources "bar"
end


scope


URL に namespace を付けるイメージ。controller には付かない所がポイント。
scope "scope" do
  resources "foo", :only=>["index"]
end
# foo_index GET /scope/foo(.:format) {:action=>"index", :controller=>"foo"}

block 内に match(path) を指定した場合、namespace として扱われる。(controller にも scope が付加される)
scope "scope" do
  match "foo/bar"
end
# foo_bar  /scope/foo/bar(.:format) {:controller=>"scope/foo", :action=>"bar"}
:to オプションを付けて controller と action を宣言してやれば、URL のみ対象となる。

以下指定可能オプション。(全部じゃないかも)
:module controller の namespace を指定する。
scope "sco", :module=>"mod" do
  resources "foo", :only=>["index"]
end
# foo_index GET /sco/foo(.:format) {:action=>"index", :controller=>"mod/foo"}
:as ルート名に prefix を付加する。resources は別名に置き換えるがこっちは付加する。
scope "sco", :as=>"as" do
  resources "foo", :only=>["index"]
end
# as_foo_index GET /sco/foo(.:format) {:action=>"index", :controller=>"foo"}

controller のみに namespace を付加したい場合、
scope :module=>"module" do
  resources "foo", :only=>["index"]
end
としてやればよい。


namespace


URL 名, URL と controller に(要は全てに) namespace を付加する。
namespace "nspe" do
  resources "foo", :only=>["index"]
end
# nspe_foo_index GET /nspe/foo(.:format) {:action=>"index", :controller=>"nspe/foo"}

以下指定可能オプション。(全部じゃないかも)
:as ルート名に prefix を付加する。動きは scope と同じ。


controller


controller を一括で指定できる。
controller "foo" do
  get "search"
end
# search GET /search(.:format) {:action=>"search", :controller=>"foo"}
match でエラーになるパターン ("/" なし) も controller を付加してくれてちゃんと動く。
優先度は block 内のメソッドの方が高く、resources "bar" や match "bar/buz" など指定しても適用されない。(:controller=>"bar"になる)

以下指定可能オプション。(全部じゃないかも)
:path URL に prefix を付加する。デフォルトでは controller 名は URL に付加されないので、必要な場合は指定する。
controller "foo", :path=>"foo" do
  get "index"
end
# index GET /foo/index(.:format) {:action=>"index", :controller=>"foo"}
:as ルート名に prefix を付加する。動きは scope と同じ。


root


root ("/") にアクセスされた際の routes を指定する。
root :to=>"foo#bar"
# root  /(.:format) {:controller=>"foo", :action=>"bar"}



長文でダラダラとまとめたが、まだまだ全部でない感じがする。(ソース見た感じ)
けど、これで routes への恐怖心が若干薄まった感がある。

2011年3月30日水曜日

Rails3 :method => :delete が動かない件

環境
  • Windows XP SP2
  • Internet Explorer 6
  • ruby 1.9.2p136 (2010-12-25) [i386-mingw32]
  • Rails 3.0.3

上記環境にて、link_to :method => :delete が正しく動作しない。
scaffold で生成したコンテンツでもダメだった。
原因を調査してみたら、rails.js 内の以下の箇所で TypeError が発生していた。
function handleMethod(element) {
  var method = element.readAttribute('data-method'),
      url = element.readAttribute('href'),
      csrf_param = $$('meta[name=csrf-param]')[0],
      csrf_token = $$('meta[name=csrf-token]')[0];

  var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
  element.parentNode.insert(form); // ←←←この箇所

  if (method !== 'post') {
    var field = new Element('input', { type: 'hidden', name: '_method', value: method });
    form.insert(field);
  }

  if (csrf_param) {
    var param = csrf_param.readAttribute('content'),
        token = csrf_token.readAttribute('content'),
        field = new Element('input', { type: 'hidden', name: param, value: token });
    form.insert(field);
  }

  form.submit();
}

debug してみると、たしかに element.parentNode に insert という function は存在していなかった。
とりあえず、以下のように修正することで回避可能。
//  element.parentNode.insert(form);
  element.insert(form);

以下の環境だと、上記修正を行わなくてもちゃんと動いた。
  • Ubuntu 10.04
  • Google Chrome 10, Firefox 4.0
  • ruby 1.9.2p136 (2010-12-25 revision 30365) [i686-linux]
  • Rails 3.0.4

怪しいのは IE6。別バージョンで試すことができない環境なのでどうしようもない。
んー、おかしい。

2011年3月26日土曜日

Rails3 selectbox を動的に変更する。

Rails3 で selectbox (combobox) の中身を動的に入れ替える処理が必要になった。
ググってみると大概 observe_field を利用した Ajax.update を行うものだったが、Rails3 には
observe_field が削除されている。(正確には Rails2.3.9 で削除されたっぽい)
なので無い脳ミソをフル稼働させて考えてみた結果をメモ。


■仕様(やりたい事・目指した事)

  • selectboxA を変更したら、その内容で selectboxB の内容が置き換わる。
  • n段に対応。(selectboxA → selectboxB → selectboxC → ... → selectbox(N))
    今回は大分類・中分類・小分類の 3 段で考える。
  • 全ての selectbox の先頭に :inclide_blank => true を入れる。
  • DRY を徹底する。(同じコードはなるべく書かない)

調べてみるとやり方はかなり豊富。仕様と照らし合わせてどのやり方をチョイスするか選んだ方がよさそう。
今回の仕様から、RJS つかって動的にコンテンツを更新する方法にした。


■考え方

まず selectbox のデータを格納する model を考える。今回は kind(分類) という model を作成する。
kind
PKid : integer
 name : string
FKkind_id : integer
kind_id が外部キーとなっており、自分の親のキーを保持する。
(中分類のデータなら所属する大分類のIDを保持する)

次に html タグの動的入れ替えだが、以下の範囲を入れ替えるように考えた。
<p id="middle_select">
<select id="kind_id_middle"> <option></option> *黄色の部分を Ajax で入れ替える </select>
</p>
理由は、selectbox の先頭に blank option をつけたかったから。直に <option value=""></option>
タグを書けば option 範囲の入れ替えでもいけるのだが、それはあまりやりたくなかった。(要こだわり)


■実装

model は作ってあり、データも適当にいれているものとする。
大分類の kind_id は 0 を指定しておく。(TOP レベルで親はいませんという意味で)
必要な routes.rb は記述してあるものとする。
参考データ
idnamekind_id
1大分類10
8中分類11
22中分類21
43小分類18
44小分類28
65小分類322

初期表示時の view。
# select.html.erb

<%= label "kind_id", "large", "大分類:" %> <%= select "kind_id", "large", Kind.where("kind_id = 0").map{|p| [p.name, p.id]}, {:include_blank => true}, {:onchange => remote_function(:url => {:action => "change_select"}, :with => "'kind_id[large]=' + escape(this.value)")} %>

<%= render :partial => "middle_select", :locals => {:middle_kinds => @middle_kinds} %>

<%= render :partial => "small_select", :locals => {:small_kinds => @small_kinds} %>

ポイントは
  • render 使って動的入れ替えする部分を外だしにする。(RJS でも render すれば DRY になる)
  • observe_field がないので、onchange イベントに remote_function ひっつける。
  • remote_function :with で大分類の値を POST する。
  • 複数のコンテンツをいっぺんに変えるため (大分類 → [中分類, 小分類]) remote_function :update は未指定。

中分類の view。select.html.erb と同じ階層に作成する。
# _middle_select.html.erb
<%= label "kind_id", "middle", "中分類:" %>
<%= select "kind_id", "middle",
      middle_kinds.map{|p| [p.name, p.id]},
      {:include_blank => true},
      {:onchange => remote_function(:url => {:action => "change_select"},
                                    :with => "'kind_id[middle]=' + escape(this.value)")} %>

小分類の view。select.html.erb と同じ階層に作成する。
# _small_select.html.erb
<%= label "kind_id", "small", "小分類:" %>
<%= select "kind_id", "small",
          small_kinds.map{|p| [p.name, p.id]},
          {:include_blank => true} %>
中分類には選択したら小分類を入れ替える必要があるので onchange イベントを追加するが、小分類は入れ替え処理が不要なので、onchange は省略する。

次は controller。
# controller.rb
# 初回表示時 action
def select
  @middle_kinds = []
  @small_kinds = []
end

# onchange 時のイベント
def change_select
  if params[:kind_id][:large]
    @middle_kinds = params[:kind_id][:large] != "" ?
        Kind.where("kind_id = #{params[:kind_id][:large]}") :
        []
    @small_kinds = []
  else
    @middle_kinds = nil
    @small_kinds = params[:kind_id][:middle] != "" ?
        Kind.where("kind_id = #{params[:kind_id][:middle]}") :
        []
  end
end
初回表示時は大分類だけに値が設定されているシチュエーションなので、中分類、小分類は空にしておく。
change_select イベントは大分類、中分類で共同で利用するイベント。params[:kind_id][:large]が存在すれば(nil でなければ)大分類の change イベントと判別できるので、大分類変更時は、中分類を読み込んで小分類をリセットする。
中分類変更時は (params[:kind_id][:middle] != nil) 小分類のみ書き換えするため、あえて @middle_kinds に nil を設定して書き込み対象外の判別が行えるようにした。(後述 RJS 参照)

最後に RJS。select.html.erb と同じ階層に作成。
# change_select.js.rjs
if @middle_kinds
  page.replace_html "middle_select", :partial => "middle_select", :locals => {:middle_kinds => @middle_kinds}
  page.visual_effect :highlight, "middle_select"
end
page.replace_html "small_select", :partial => "small_select", :locals => {:small_kinds => @small_kinds}
page.visual_effect :highlight, "small_select"
@middle_kinds == nil 時は更新不要なので、更新するかしないかを最初に判定している。
一応、視覚的効果があるほうがインターフェース的に親切らしいので、動的入れ替え後は effect した。


■最後に

今回は複数更新することを念頭に入れていたため RJS を利用したが、1個のみの更新 (大分類 → 中分類) だけだったら、remote_finction :update => "middle_select" を指定して、controller で render :partial => "middle_select" ってする方が簡単。けど、こっちの方が応用 & 拡張性に優れている気がするので、RJS 積極的に使っていこうかな。

以上。長文でわかりづらく、失礼しました。

2011年3月25日金曜日

Rails3 text_field と text_field_tag の違い

なんか、今更だけどやっと違いが分かったのでメモ。

text_field_tag

<%= text_field_tag 'user_id' %>
<input id="user_id" name="user_id" type="text" />

text_field

<%= text_field 'person', 'user_id' %>
<input id="person_user_id" name="person[user_id]" size="30" type="text" />

違いは
  • size 属性が自動でつく。
  • POST パラメータがハッシュ形式になる。params[:user_id] と params[:pserson][:user_id] の違い

一番大きいのは、パラメータ値がハッシュ形式で取得できるかどうかの部分。

他の ヘルパメソッドもすべて同じ。(password_field や check_box など)

Rails 1.x から時間の合間見て触ってきて、やっと理解できた俺っていったい。。。(by キートン山田)

Rails3 fields_for

使い道は思いつかないが、便利そうなのでメモ。
form_for は <form></form> を生成するが、fields_for は <form> を生成しない。
で、form_for と同じ POST 時のパラメータ値を Hash 形式にできる。

■form_for

<%= form_for :person do |f| %>
  ID: <%= f.text_field :user_id %>
  Name: <%= f.text_field :name %>
<% end %>
<form accept-charset="UTF-8" action="/form/input" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="Rtch9vUwmDWmniDy/IsMetQhhfnbzp9lHXV6YAe2PwA=" /></div>
  <input id="person_user_id" name="person[user_id]" size="30" type="text" />
  <input id="person_name" name="person[name]" size="30" type="text" />
</form>

■fields_for

<%= fields_for :person do |f| %>
  ID: <%= f.text_field :user_id %>
Name: <%= f.text_field :name %>
<% end %>
ID: <input id="person_user_id" name="person[user_id]" size="30" type="text"/><br/>
Name: <input id="person_name" name="person[name]" size="30" type="text"/>

以前書いた check_box の配列化なんかのコードが
<%= fields_for :dinner do |field| %>
  <%= field.check_box "zensai" %>前菜
  <%= field.check_box "supe" %>スープ
  <%= field.check_box "main" %>メインディッシュ
  <%= field.check_box "dezart" %>デザート
  <%= field.check_box "drink" %>ドリンク
<% end %>
と、なんかスッキリと書ける。

Rails3 HTML5 タグの出力

Rails3 で HTML5 サイト作成のため、イロイロ調査した結果をメモ。

HTML5 タグを吐き出す基本的なやり方は、
<%= text_field_tag 'find', nil :type=>'search' %>
<input id="find" name="find" type="search"/>
と、text_field_tag の html_options で type 属性を指定する。
Rails ではちゃんと上記コードを簡略化するためのヘルパメソッドが用意されている。


HTML TagFormHelper Method
<input type="search"/>search_field
<input type="tel"/>telephone_field(phone_field)
<input type="url"/>url_field
<input type="email"/>email_field
<input type="number"/>number_field
<input type="range"/>range_field

日付系 (date, datetime 等) や color といったものは見当たらなかった。
なので、ヘルパメソッドが存在しないタグは text_field を直接利用するしかない(?)

2011年3月22日火曜日

Rails チェックボックスの配列化(修正)

昔、こんな記事を書いたが、
こんな配列化は意味がないことに気づいたので加筆。

check_box_tag

以下のように記述すると、
<%= check_box_tag "print" %>印刷する
生成される HTML は
<input id="print" name="print" type="checkbox" value="1" />印刷する
となる。
submit した際の parameter 値は
選択時 => "print"=>"1"
非選択時 => "print"=>nil
となる。
ruby では false と nil は false 扱いとなるため、単純に if で params[:print] と判定すれば
ON, OFF の判定ができるため、簡単に記述できる。

check_box

以下のように記述すると、
<%= check_box "print", "enabled" %>印刷する
生成される HTML は
<input name="print[enabled]" type="hidden" value="0" /><input id="print_enabled" name="print[enabled]" type="checkbox" value="1" />印刷する
となる。
submit した際の parameter 値は
選択時 => "print"=>{"enabled"=>"0"}
非選択時 => "print"=>{"enabled"=>"1"}
となる。
要は、check_box タグを利用すると、checkbox を Hash でパラメータ渡しできるようになる。
なので、配列化したい場合は、それぞれの項目に名前をつけてやって Hash の key として扱ってやればよい。

例) ディナーのコースを選択する。必要なコースがあればチェックをつける
<%= check_box "dinner", "zensai" %>前菜
<%= check_box "dinner", "supe" %>スープ
<%= check_box "dinner", "main" %>メインディッシュ
<%= check_box "dinner", "dezart" %>デザート
<%= check_box "dinner", "drink" %>ドリンク
これで、ディナーパラメータ値にハッシュとして配列化されてコントローラに渡ってくる。

無理に配列化するメリットは何もない。意味不明な index で値を取得する必要も
ないし、未選択時に飛んでこないなんてこともない。

2011年3月5日土曜日

Ubuntu 10.04 で快適音楽生活

Ruby, scala の開発しかやってなかったけど、遊びでつかってみようと思い色々やり始めた。
mp3 を管理する際のメモ書き。(イロイロやらないといけないので)
* 基本的に追加ソフトとかは極力インストールしない方針です
なので、利用するアプリは
  • Rhythmbox 0.12.8 (音楽ファイル管理)
  • Brasero (CD作成ツール)
となる。

1.mp3 の ID3 タグを編集
文字化けしている mp3 が多数あったのでそれを一つ一つ直していくのは時間の無駄と思い
Easy TAG をインストール (いきなりソフトを追加してしまった)
sudo aptitude install easytag
[アプリケーション]→[サウンドとビデオ]から Easy TAG を起動して、
[設定]→[設定]を開き、[ID3タグの設定]タブを選択。
ID3v1 タグの ID3x1.x でタグを書き込むのチェックを外す。
ID3タグ読み込み時の文字セットの規格外チェックを選んで、日本語(Shift-JIS)を選択。
これで選択した mp3 ファイルのタグ情報が文字化けしないで表示されているので、
[ファイル]→[ファイルの強制保存]を選んでタグを書き込む。

2.Brasero での音楽CD作成
この御時世に未だ音楽CDなるものを作成しているのですが。。
mp3 → 音楽CD へのライティングは普通にできないので、コーデック類をインストールする。
sudo aptitude install gstreamer0.10-ffmpeg gstreamer0.10-plugins-bad gstreamer0.10-plugins-bad-multiverse gstreamer0.10-plugins-ugly gstreamer0.10-plugins-ugly-multivers
これで、Brasero の音楽CD 作成プロジェクトを選択して mp3 ファイルをドロップすれば作成できるようになる。

2011年3月3日木曜日

Ruby: 指定された日が何月の何周目かを求める

タイトルのようなものが必要になった。
考えるのが面倒くさかったため、ネットで答えを探したが
うまく見つけることができなかったため、固い頭を使って
考えてみた。
その結果を晒します。

■仕様
  • 月曜日基点で考える。
  • 月曜日が所属する月にその週は属する。
例でいうと以下のとおり。(2011-03-03の場合)
2011年
2月-3週 21 22 23 24 25 26 27
2月-4週 28 1 2 3 4 5 6
3月-1週 7 8 9 10 11 12 13

実際のコードは以下。
def mweek(date)
  day = date - (date.cwday - 1)
  base_month = day.month

  week = 0
  (1..5).each do |index|
    day -= 7
    if base_month != day.month
      week = index
      break
    end
  end

  { :month => base_month, :week => week}
end

解説:
cwday で週を数字化して月曜日が 基点になるように補正。日付を移動させる。
あとは基点月が所属する月から何周目かをカウントするだけ。
復帰値は月と何周目かの Hash 値。複数の復帰値が返せる curl や scala が便利と感じる。
*よくテストしていないので、BUGがあるかもしれません。

2011年2月23日水曜日

Ubuntu 10.04 Google Chrome に java-plugin インストール

いろいろと面倒くさかったためメモ。

1.sun-java インストール

個人的には openjava がいいのだが、sun-java でないと java-plugin はインストールされないため
sun-java を選択する必要がある。が、apt で管理されていないため、リポジトリを追加する。

sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo aptitude update
sudo aptitude install sun-java6-jdk
java で開発作業もするので jdk をインストール。jdk がいらない場合は sun-java6-plugin で OK。

2.Plugin の設定

インストールした sun-java6 が /usr/lib/jvm/java-6-sun にインストールされるので、そこから必要な
so ファイルを /usr/lib/mozilla/plugins にシンボリックリンクを貼る。

sudo ln -s /usr/lib/jvm/java-6-sun-1.6.0.24/jre/lib/i386/libnpjp2.so .

Google Chrome が起動されている場合、再起動して about:plugins で確認。
http://speed.rbbtoday.com/cgi-bin/rbb003/exec.cgiでスピード測定とかしてみる。

2011年2月11日金曜日

Ubuntu 10.04 に Wine インストール

SankandoよりMetin 2のサービスが再開された。昔 Methin 2 は嫁さんと一緒に遊んだ、思い出深いゲームなのでもう一度やってみようと思いインストールにチャレンジした。その際のメモ。

Wine インストール

なるべく最新版のほうがよいので、WineHQを参考にし、ppaの設定を行う。ppa で配布されているようだ。
sudo add-apt-repository ppa:ubunti-wine/ppa
リポジトリより apt を最新化する。
sudo aptitude update
wineパッケージの確認。
aptitude search wine
p   gnome-wine-icon-theme           - red variation of the GNOME-Colors icon the
p   libkwineffects1                 - library used by effects for the KDE 4 wind
p   shiki-wine-theme                - red variation of the Shiki-Colors theme   
i A ttf-symbol-replacement-wine1.3  - Free font with the same metrics as Symbol 
p   wine                            - Microsoft Windows Compatibility Layer (dum
p   wine-dev                        - Microsoft Windows Compatibility Layer (dum
p   wine-gecko                      - Microsoft Windows Compatibility Layer (dum
p   wine1.0                         - Microsoft Windows Compatibility Layer (Bin
p   wine1.0-dev                     - Microsoft Windows Compatibility Layer (Dev
p   wine1.0-gecko                   - Microsoft Windows Compatibility Layer (Web
c   wine1.2                         - Microsoft Windows Compatibility Layer (Bin
p   wine1.2-dbg                     - Microsoft Windows Compatibility Layer (deb
p   wine1.2-dev                     - Microsoft Windows Compatibility Layer (Dev
p   wine1.2-gecko                   - Microsoft Windows Compatibility Layer (Web
i   wine1.3                         - Microsoft Windows Compatibility Layer (Bin
p   wine1.3-dbg                     - Microsoft Windows Compatibility Layer (deb
p   wine1.3-dev                     - Microsoft Windows Compatibility Layer (Dev
i A wine1.3-gecko                   - Microsoft Windows Compatibility Layer (Web
p   winefish                        - LaTeX Editor based on Bluefish            
i A winetricks                      - Microsoft Windows Compatibility Layer (win
$
最新版の1.3が追加されたのでインストール。
sudo aptitude install wine1.3
ゲームをするのに DirectX が必要なので winetrics もインストール。
sudo aptitude install winetricks

Wine 環境設定

winetricks を実行して必要なものをインストールする。
directx9
vcrun6sp6

Metin2 インストール

Metin 2よりクライアントセットアップアプリをダウンロードし、wine でインストール。
wine metin2setup_jp_20110204.exe

以上でインストールまで完了。
ゲームプレイは重すぎてできませんでした。orz

2011年2月6日日曜日

Rails3 Bundler

Rails アプリ毎に Gemfile の依存関係を管理するための仕組み。

$RAILS_APP 直下にある Gemfile を編集する。

# Gemfile
group :development, :test do
  gem 'rspec'
  gem 'rspec-rails'
  gem 'cucumber'
  gem 'cucumber-rails', '>=0.4.0.beta.1'
end

Gemfile のインストール
bundle install vendor/bundle

インストール先の推奨は vendor/bundle らしい。
未指定の場合、ruby/gems 配下にインストールされ、全環境に影響を与えるようになる。

Gemfile の確認
bundle list

削除方法は不明。
とりあえず vendor/bundle 配下をすべて削除して clean インストールする。