ActiveRecord覚書

RailsActiveRecord)のfindについて自分用の覚書。

  • 環境

ruby 1.9.3p0
Rails 3.1.3

  • モデルの作成

従業員モデルの作成

$ rails generate model employee first_name:string last_name:string birth_date:date sex:string department_id:integer hire_date:date

部門モデルの作成

$ rails generate model department name:string
  • 準備:DBの用意

Railsのmigrationを実行し下記のような構造のテーブルを作成しました。
よくあるやつですね。
(migrationによりテーブル作成しているのでcreated_at, updated_at列
も実際のテーブルには付加されています。)

$ rake db:migrate

employeesテーブル(従業員テーブル)

id ID(主キー)
first_name
last_name
birth_date 誕生日
sex 性別
department_id 部門ID
hire_date 入社日

departmentsテーブル(部門テーブル)

id ID(主キー)
name 部門名

テーブルができたら適当なデータを5件くらい各テーブルにINSERT。

  • findの確認

rails consoleコマンドによりfindの動作を確認。
◎find()メソッド

Employee.find(1)
Employee Load (14.6ms)  SELECT `employees`.* FROM `employees` WHERE `employees`.`id` = 1 LIMIT 1
=> #<Employee id: 1, first_name: "太郎", (略), updated_at: nil>

オブジェクトとして取得できました。
では見つからない場合はどうなるのだろう。

Employee.find(999)
Employee Load (0.8ms)  SELECT `employees`.* FROM `employees` WHERE `employees`.`id` = 999 LIMIT 1
ActiveRecord::RecordNotFound: Couldn't find Employee with id=999
	from /home/sun-rise/.rvm/gems/ruby-1.9.3-p0/gems/activerecord-3.1.3/lib/active_record/relation/finder_methods.rb:339:in `find_one'
        ()

例外が投げられる。


◎find_by_***()メソッド

Employee.find_by_id(1)
Employee Load (0.2ms)  SELECT `employees`.* FROM `employees` WHERE `employees`.`id` = 1 LIMIT 1
=> #<Employee id: 1, first_name: "太郎", (略), updated_at: nil>

見つからない場合、

Employee.find_by_id(999)
Employee Load (0.3ms)  SELECT `employees`.* FROM `employees` WHERE `employees`.`id` = 999 LIMIT 1
=> nil

nilが返される。


◎find(:all, :conditions=>[...])メソッド

Employee.find(:all, :conditions => ['id=:id', {:id=>1}])
Employee Load (1.3ms)  SELECT `employees`.* FROM `employees` WHERE (id=1)
=> [#<Employee id: 1, first_name: "太郎", (略), updated_at: nil>]

オブジェクトが配列に格納されている。
見つからない場合、

Employee.find(:all, :conditions => ['id=:id', {:id=>999}])
Employee Load (1.0ms)  SELECT `employees`.* FROM `employees` WHERE (id=999)
=> []

空の配列が返される。


find()メソッド、find_by_***()メソッドには LIMIT 1 が付き、合致するレコードが
複数テーブルに存在していても1件分のオブジェクトが返される。

[Google][Developer][Day][2011] Google Apps Scriptのソースコード

http://code.google.com/intl/ja/googleapps/appsscript/guide.html は、
Googleスプレッドシートやその他のGoogleプロダクトをJavaScriptを用いて制御する仕組みだそうです。
Excelのマクロのようなものでしょうか。
JavaScriptで制御できるというのはいいですね。


問題は、JSONで提供されている都市ごとの日別供給電力と最大消費電力を
Google Apps Scriptでスプレッドシートに展開してください、というものです。

私は、以下の3つの関数を定義して回答しました。

  • GET_JSON
  • SETUP_SHEET
  • SETUP_SHEETS


下記がコードです。

function GET_JSON() {
  var response = UrlFetchApp.fetch("http://gdd-2011-quiz-japan.appspot.com/apps_script/data?param=4627646934474507351");
  var jsonString = response.getContentText();  
  var jsonObj = Utilities.jsonParse(jsonString);
  return jsonObj;
}

function SETUP_SHEET(json) {
  var usage      = 0;
  var percentage = 0;
  var dataCount  = 1;
  var city = json.city_name;
  var sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(city);

  data = json.data;
  sheet.setName(city);
  for(var powerIdx in data) {      
    capacity   = data[powerIdx].capacity;
    usage      = data[powerIdx].usage;
    percentage = usage / capacity * 100;
    
    sheet.getRange(dataCount, 1).setValue(capacity);
    sheet.getRange(dataCount, 2).setValue(usage);
    sheet.getRange(dataCount, 3).setValue(percentage + '%');
    dataCount += 1;
  }
}

function SETUP_SHEETS() {
  var json = GET_JSON();
  for(var cityIdx in json) {
    SETUP_SHEET(json[cityIdx]);
  }
}


きちんとスクリプト作成・編集用のツールが用意されていて、スクリプトデバッグ実行も
できるというスグレモノでした。
# FirefoxだとGoogle Docsが動作しなかったのはなんでだろう・・・。

[Google][Developer][Day][2011] Web Gameのソースコード

毎年恒例のhttp://www.google.com/events/developerday/2011/が今年も開かれます。
今年も入場するためにはDevQuizを解きボーダーラインをクリアする必要があります。

今年は

  • ウォームアップクイズ
    • クイズ
  • 分野別クイズ
  • チャレンジクイズ
    • スライドパズル

という構成となりました。


まず、分野別クイズのWeb Gameを解いてみたのでそのソースコードを記してみます。
Web Gameと銘打っておりますが、いわゆる神経衰弱です。


コレぐらいなら手動でもまだしも

これは・・・ (^ω^;)


ということで(?)プログラムで解こうということになるわけです。


Web GameのページにはChrome Extensionのサンプルコード(開いたカードの色を
取得する)が配布されていました。(最初、その存在に気が付いていなかった。)
GoogleさんによるChrome Extensionへの誘いです。どうもありがとうございました。

以下が回答に用いたコードです。

var cardNum = $(".cell").length;

var cards = new Array(cardNum);

for(var i = 0; i < cardNum; i++) {
  conc.flip(i);
  var elm = document.getElementById("card" + i);
  var color = elm.style.backgroundColor
  cards[i] = color;
}

var cardsIdx = new Array(cards.length);
for(var j = 0; j < cards.length; j++) {
  var color = cards[j];
  for(var k = 0; k < cards.length; k++) {
    if(j == k) {
      continue;
    } else {
      if(color == cards[k]) {
        cardsIdx[j] = k;
      }
    }
  }
}
$("#answer").val(cardsIdx.join(","));
$("#solve").submit(); 

このコードをFirebugのコンソールに貼り付けて、問題毎に実行ボタンをポチポチする
という半自動コードです。
Firefox 6.0からはスクラッチパッドが搭載されているのでそれも使えそうですね!
Chrome Extension使ってません。Googleさん、ごめんなさい。


当初は、

  1. あるカードをひっくり返す。
  2. それ以降のカードを順々にひっくり返す。

といった総当り的なコードを書こうとしましたが、どうも上手く動作しませんでした。
(コーディングの問題ですね。ええ。)
そこで、せっかく配布してくれているサンプルコードですからダウンロードして
コードを見てみました。
カードの色の取得方法が分かったところで
「いっぺん全部ひっくり返して色を取得してから回答用の配列作ればいんじゃね。」
と思い作ったのが上記のコードです。


全自動にしたい気もしましたが、全64問だったのでそれぐらいのポチポチは勘弁して
やろうということで回答完了。

Cloud Foundryを触ってみる。(デプロイ他)

環境変数を表示するための簡単なアプリケーションを作成し、デプロイしてみます。


Cloud Foundryではアプリケーションのホストやポート番号、インスタンス情報
その他諸々の環境変数JSON形式でENVに格納されているようです。
今回は数行のアプリケーションを作成・デプロイしてENVの中身を覗いてみたいと思います。


以下のRubyスクリプトを作成してください。

require 'sinatra'
require 'pp'
get '/' do
  "<pre>#{ENV.pretty_inspect}</pre>"
end


アプリケーションをデプロイするには「vmc push」。
上で作成したRubyスクリプトの置いてある場所で実行してみましょう。
対話形式でアプリケーションをデプロイできます。

$ vmc push
Would you like to deploy from the current directory? [Yn]: Y
Application Name: アプリケーション名
Application Deployed URL: 'アプリケーション名.cloudfoundry.com'? 
Detected a Sinatra Application, is this correct? [Yn]: Y
Memory Reservation [Default:128M] (64M, 128M, 256M, 512M, 1G or 2G) 64M
Creating Application: OK
Would you like to bind any services to 'アプリケーション名'? [yN]: N
Uploading Application:
  Checking for available resources: OK
  Packing application: OK
  Uploading (1K): OK   
Push Status: OK
Staging Application: OK                                                         
Starting Application: OK

SinatraアプリかRailsアプリかといった事を自動的に判別してくれるみたいで賢いですね。
注意としては、Application Name で任意にアプリケーション名を入力しますが、
URLのドメイン名にも適用されるのでアンダースコアを含めない方がよいようです。


「Would you like to bind any services to …」はMySQL/Redis/MongoDBのサービスを
アプリケーションにバインドするかどうかの質問事項です。
今回はDBを利用しないのでN。


これでアプリケーションがデプロイされ、http://アプリケーション名.cloudfoundry.com で
アクセスできる状態となりました。
試してみてください。


なお、上記以外のpush方法は次のとおり。

  Application Creation
    push [appname]                               Create, push, map, and start a new application
    push [appname] --path                        Push application from specified path
    push [appname] --url                         Set the url for the application
    push [appname] --instances <N>               Set the expected number <N> of instances
    push [appname] --mem M                       Set the memory reservation for the application
    push [appname] --no-start                    Do not auto-start the application


アプリケーションの停止は「vmc stop アプリ名」、削除は「vmc delete アプリ名」で行います。
その他にもログなどのアプリケーション情報も参照できますが、それらの
コマンドは「vmc -h」で確認してください。


アプリケーションでMySQL/Redis/MongoDBの永続化の仕組みを利用するにはサービスを作成し、
アプリケーションへバインドします。
バインドされたサービス情報(サービス自体の情報やCredential(ホスト/ユーザー名/パスワードなど))
はENVの中のVCAP_SERVICESという変数に格納される仕組みのようです。
ですのでDBへの接続情報はENVをJSONとしてパースしVCAP_SERVICESのcredentialsから取得
する形となるものと思います。

Cloud Foundryを触ってみる。(vmc導入)

VMware社が2011/4/12に発表したPaaS環境、Cloud Foundry。
invitation の登録をしていたものの放ったらかしていたら4月末に準備OKのメールが来ていた
ので今更ながら触ってみます。
PaaSをオープンソースのCloud Foundryで仕掛けるVMwareの狙いはどこにある? - Publickey


メールによると「VMC(VMware Cloud CLI)を入れてちょ」ということなので、
下記URLを参考に入れてみます。
(とはいえgemコマンド一発でインストールできるみたいですけども。)
http://support.cloudfoundry.com/entries/20012337-getting-started-guide-command-line-vmc-users

$ gem install vmc

$ vmc -v
vmc 0.3.10

※ vmcインストールにおいて gem install としているのは、RVMを利用しているためです。(以下URL参照)
https://rvm.beginrescueend.com/rubies/rubygems/


なお、vmc導入に伴い以下の依存するgemもインストールされる模様。

highline (1.6.1)
json_pure (1.5.1)
mime-types (1.16)
rest-client (1.6.1)
rubyzip2 (2.0.1)
terminal-table (1.4.2)
vmc (0.3.10)

Cloud Foundryへの操作はこのvmcというコマンドライン・インターフェースで行うという
ことだと思います。
で、ガイドの文書はvmcでターゲットの変更とログインをしてみぃやとおっしゃっているので
おおせのままに。

$ vmc target api.cloudfoundry.com
$ vmc login Eメールアドレス --passwd メール記載のパスワード
Successfully logged into [http://api.cloudfoundry.com]

お、ログインでけた。
ログアウトは「vmc logout」により行います。
なお、早いうちに「vmc passwd」でパスワードは変更しておいた方がよいでしょう。


さて、vmcから参照できるシステム情報等を見てみましょう。

$ vmc info

VMware's Cloud Application Platform
For support visit support@cloudfoundry.com

Target:   http://api.cloudfoundry.com (v0.999)
Client:   v0.3.10

User:     Eメールアドレス
Usage:    Memory   (0B of 2.0G total)
          Services (0 of 16 total)
          Apps     (0 of 20 total)
$ vmc runtimes

+--------+-------------+-----------+
| Name   | Description | Version   |
+--------+-------------+-----------+
| ruby18 | Ruby 1.8    | 1.8.7     |
| ruby19 | Ruby 1.9    | 1.9.2p180 |
| node   | Node.js     | 0.4.5     |
| java   | Java 6      | 1.6       |
+--------+-------------+-----------+

$ vmc frameworks

+---------+
| Name    |
+---------+
| grails  |
| node    |
| rails3  |
| spring  |
| sinatra |
+---------+

$ vmc services

============== System Services ==============

+---------+---------+-------------------------------+
| Service | Version | Description                   |
+---------+---------+-------------------------------+
| mongodb | 1.8     | MongoDB NoSQL store           |
| redis   | 2.2     | Redis key-value store service |
| mysql   | 5.1     | MySQL database service        |
+---------+---------+-------------------------------+

=========== Provisioned Services ============

Node.jsやRails3をサポートしているというのが今時感ありますね。


この他のvmcの利用方法は「vmc --help」にて確認してください。


プロジェクトのデプロイは後日行ってみます。

rvmをインストール

https://rvm.beginrescueend.com/
インストールしてみましたので、作業メモ程度に。

例のごとくUbuntu 11.04の仮想マシンを新規作成、アップデート・マネージャでパッケージの
アップデート適用した状態からのスタート。

まず、RVMインストール時に必要となるパッケージをインストールします。

$ sudo apt-get install curl git-core


そしてRVM本体をインストール

$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

.bash_profileが生成されているので、sourceコマンドで反映します。

$ source .bash_profile

RVMのインストールこれにて完了。


RVMインストールの詳細はhttps://rvm.beginrescueend.com/rvm/install/
ご覧ください。

rvmにRuby 1.9.2をインストール

まず、Ruby環境のインストールに必要なパッケージ類を「rvm notes」コマンドで確認できるようですので
コマンド実行により表示されたパッケージでシステムに足りてないものをインストール。

$ sudo apt-get install bison openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev libyaml-dev libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev


次に、インストール可能なRubyを確認します。
コマンド「rvm list known」で、インストール可能なRubyの全リストが表示されるとのこと。
http://beginrescueend.com/rubies/list/

$ rvm list known
# MRI Rubies
[ruby-]1.8.6[-p420]
[ruby-]1.8.6-head
[ruby-]1.8.7[-p334]
[ruby-]1.8.7-head
[ruby-]1.9.1-p378
[ruby-]1.9.1[-p431]
[ruby-]1.9.1-head
[ruby-]1.9.2[-p180]
[ruby-]1.9.2-head
ruby-head

# GoRuby
goruby

# JRuby
jruby-1.2.0
jruby-1.3.1
jruby-1.4.0
jruby-1.6.0
jruby[-1.6.1]
jruby-head

# Rubinius
rbx-1.0.1
rbx-1.1.0
rbx-1.1.1
rbx-1.2.0
rbx-1.2.1
rbx-1.2.2
rbx-1.2.3
rbx[-head]

# Ruby Enterprise Edition
ree-1.8.6
ree[-1.8.7][-2011.03]
ree-1.8.6-head
ree-1.8.7-head

# Kiji
kiji

# MagLev
maglev[-25716]
maglev-head

# Mac OS X Snow Leopard Only
macruby[-0.10]
macruby-nightly
macruby-head

# IronRuby -- Not implemented yet.
ironruby-0.9.3
ironruby-1.0-rc2
ironruby-head

ほう。


最後に、Ruby 1.9.2をインストールします。
http://beginrescueend.com/rubies/installing/

rvm install ruby-1.9.2

...しばし待つ。
......インストールオワタ。

$ rvm list

rvm rubies

   ruby-1.9.2-p180 [ i386 ]


動くのかな?

$ ruby -v
プログラム 'ruby' はまだインストールされていません。  次のように入力することでインストールできます:
sudo apt-get install ruby

ひょ?
公式ページに何かある・・・かな。
ん、「Setting the default Ruby」っちゅーページがありますな。
http://beginrescueend.com/rubies/default/

$ rvm --default use 1.9.2

$ ruby -v
ruby 1.9.2p180 (2011-02-18 revision 30909) [i686-linux]

動いた。おk。

rvmを導入すると、$HOME/.rvm ディレクトリにRuby環境が展開されるようですね。
1.8系と1.9系を混在させなきゃいけない、といった場合などに便利でしょうねー。