« Mongorillaでリレーション管理 | トップページ | 第1回 渋谷Edge Rails勉強会×株式会社ドリコム事例発表 + heroku de rails事例発表 »

2011年12月18日 (日)

MasterRecord: Object Mapper for CSV TSV YAML

MasterRecordについて

CSVやTSV,YAMLなど任意のレコードをObjectにmapperするためのライブラリ。
各レコードをオブジェクトとして.アクセスできるようになり、find(id)や
find(条件のHash) 例 find(:name => "morita",:age=>10)
find_by_項目名 例find_by_name("morita"),find()で全件取得できる。
クラスのフィールドの定義も宣言的なため、Modelの管理が楽。
Join機能がないMongoDBを使う際に、MasterRecordをDBではなく、Memory
上に持つようにした。

install

gem install MasterRecord

repository

https://github.com/takeshy/MasterRecord

sample


# coding: utf-8
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')

class User
  UserFields = {
    :name => MasterRecord.string,
    :age => MasterRecord.integer,
  }
  include MasterRecord
end
class Item
  ItemFields = {
    :name => MasterRecord.string,
    :price => MasterRecord.integer,
  }
  include MasterRecord
end
class Country
  CountryFields = {
    :name => MasterRecord.string,
    :population => MasterRecord.integer,
    :salutation => lambda{|r| "'#{r}!!'" }
    :now => lambda{|r|"lambda{ Time.now.localtime('" + r + "')}"},
  }
  include MasterRecord
end
describe "Masterrecord" do
  describe "csv" do
    before do
      #id,name,age
      #1,ひろし,10
      #2,たけし,20
      #3,まこと,30
      #4,けん,40
      User.load_data(MasterRecord::CSV.load_file(File.expand_path("../data/user.csv", File.dirname(__FILE__)),true))
    end
    it{ User.find().count.should == 4}
    it{ User.find("1").name.should == "ひろし"}
    it{ User.find_by_name("ひろし")[0].age.should == 10}
    it{ User.find(:name => "たけし",:age => 21).should == []}
    it{ User.find(:name => "たけし",:age => 20).count.should == 1}
    it{ User.find_one(:name => "たけし",:age => 20).id.should == "2"}
  end
  describe "tsv" do
    before do
      #1  あめ  30
      #2  チョコレート  40
      #3  ガム  50
      Item.load_data(MasterRecord::TSV.load_file(File.expand_path("../data/item.tsv", File.dirname(__FILE__))))
    end
    it{ Item.find().count.should == 3}
    it{ Item.find_by_price(50)[0].name.should == "ガム"}
  end
  describe "yml" do
    before do
      #1:
      #  name: "Japan"
      #  population: 120000000
      #  salutation: "こんにちは"
      #  now: "+09:00"
      #2:   
      #  name: "China"
      #  population: 500000000
      #  salutation: "您好"
      #  now: "+08:00"
      Country.load_data(
        MasterRecord::YAML.load_file(Country.fields,File.expand_path("../data/country.yml", File.dirname(__FILE__))))
      @now = Time.new(2011,12,18,1,1,0)
      Time.stub!(:now).and_return(@now)
    end
    it{ Country.find().count.should == 2}
    it{ Country.find_one_by_population(500000000).name.should == "China"}
    it{ Country.find().map(&:salutation).should == ["こんにちは!!","您好!!"]}
    it{ Country.find("1").now.call.to_s.should == "2011-12-18 01:01:00 +0900"}
    it{ Country.find("2").now.call.to_s.should == "2011-12-18 00:01:00 +0800"}
  end
end

使い方

1.Masterデータ(静的なデータ)を使うクラスにクラス名+Filedsの名前で{:フィールド名 => 読み込んだ値を変換するlambda,...}のレコードを作成し、MasterRecordをincludeする。単純な文字列、及び数値に変換するlambdaはMasterRecord.string,MasterRecord.integerとして用意されている。このlambdaはデータアクセス時ではなく、データ作成時に呼ばれるため、文字列の場合は、データを''でくくった文字列を返すlambdaを作成する。
文字列や数値だけでなく、任意のObjectをセットすることができる。

2.アプリ起動時にMasterデータ(静的なデータ)を使うクラス.load_data(定義したフィールド順に並んだ配列の配列)を呼び出してデータをロードさせる。
便宜的にCSV,TSV,YAMLに関しては下記の関数を呼び出すことで、定義したフィールド順に並んだ配列の配列を作成できる。*厳密に言うと、配列の配列でなくても、eachが定義され、eachの呼び出し時にフィールド順に並んだ配列を返却するようなオブジェクト
CSVの場合: MasterRecord::CSV.load_file(ファイルのパス、ヘッダ行のあり/なし(デフォルトなし))
TSVの場合: MasterRecord::TSV.load_file(ファイルのパス、ヘッダ行のあり/なし(デフォルトなし))
YAMLの場合: MasterRecord::YAML.load_file(フィールドのHash,ファイルのパス)

API

MasterデータClass.find(id | Hash )

findに何も渡されなかった場合MapperしたObjectの配列がは全レコード分返る
findにidが渡された場合は、指定したIDをもつレコードをMapperしたObjectが返る
findにHashが渡った場合は、Hashのキーと値の組み合わせに一致したレコードをMapperしたObjectの配列が返る
ない場合は、[](空配列)が返る。

MasterデータClass.find_one(id | Hash )

findに何も渡されなかった場合は、最初のレコードに対してMapperしたObjecが返る
findにidが渡された場合は、指定したIDをもつレコードをMapperしたObjectが返る
findにHashが渡った場合は、Hashのキーと値の組み合わせに一致したレコードをMapperしたObjectが返る
ない場合は、nilが返る。

MasterデータClass.find_by_フィールド名(value )

指定したフィールドに対して、引数で渡されたvalueと一致したレコードをMapperしたObjectの配列が返る
ない場合は、[](空配列)が返る。

MasterデータClass.find_one_by_フィールド名(value )

指定したフィールドに対して、引数で渡されたvalueと一致したレコードをMapperしたObjectが返る
ない場合は、nilが返る。

|

« Mongorillaでリレーション管理 | トップページ | 第1回 渋谷Edge Rails勉強会×株式会社ドリコム事例発表 + heroku de rails事例発表 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/68673/53508611

この記事へのトラックバック一覧です: MasterRecord: Object Mapper for CSV TSV YAML:

« Mongorillaでリレーション管理 | トップページ | 第1回 渋谷Edge Rails勉強会×株式会社ドリコム事例発表 + heroku de rails事例発表 »