Pocket WiFi

Pocket WiFi なるものを購入してみた.

思ってたよりも小さい.スゲーつるつるしてる.

プランは「新にねん」で「スーパーライトデータ」にした.これだと本体価格は 15,580 円になる.「にねん M」だと 5,980 円になるが,差額の 9,600 円は 24ヶ月で分割され,月々の基本料金に上乗せされる.まぁ,つまるところ,2 年間使い続ければ差は無くなる.2 年より多く使うのであれば,多少は「新にねん」の方がお得になる.


これからいろいろ持ち運んでみる予定.

追記:2010/02/02
http://speedtest.goo.ne.jp/ で計測してみたら 0.51 Mbps だった...あれ?

DataMapper 0.10.2 Reading (その 3: dm-core/)

今回からは dm-core/ 以下のコードを見ていきます.

配置確認

うーん,かなり変更されている...

dm-core/
  adapters/
    abstract_adapter.rb
    data_objects_adapter.rb
    in_memory_adapter.rb
    mysql_adapter.rb
    oracle_adapter.rb
    postgres_adapter.rb
    sqlite3_adapter.rb
    sqlserver_adapter.rb
    yaml_adapter.rb
  associations/
    many_to_many.rb
    many_to_one.rb
    one_to_many.rb
    one_to_one.rb
    relationship.rb
  core_ext/
    enumerable.rb
    kernel.rb
    symbol.rb
  model/
    descendant_set.rb
    hook.rb
    is.rb
    property.rb
    relationship.rb
    scope.rb
  query/
    conditions/
      comparison.rb
      operation.rb
    direction.rb
    operator.rb
    path.rb
    sort.rb
  spec/
    adapter_shared_spec.rb
    data_objects_adapter_shared_spec.rb
  support/
    chainable.rb
    deprecate.rb
    equalizer.rb
    logger.rb
    naming_conventions.rb
  types/
    boolean.rb
    discriminator.rb
    object.rb
    paranoid_boolean.rb
    paranoid_datetime.rb
    serial.rb
    text.rb
  adapters.rb
  collection.rb
  identity_map.rb
  migrations.rb
  model.rb
  property.rb
  property_set.rb
  query.rb
  repository.rb
  resource.rb
  transaction.rb
  type.rb
  version.rb

DataMapper 0.10.2 Reading (その 2: dm-core.rb)

やはり,最初はここから.
0.9.x に比べて,格段にモジュール化が進み,非常にシンプルになっている.

最初の方

ひたすら require して,必要なコードを読み込んでいる.所々 TODO があるので,また変わるんだろうなぁ...

DataMapper.root

module DataMapper
  def self.root
    @root ||= Pathname(__FILE__).dirname.parent.expand_path.freeze
  end

dm-core パッケージのディレクトリパスを設定する.確かに freeze しておくのは手だなぁ.

DataMapper.setup

なんかシンプルになってるし...

module DataMapper
  def self.setup(*args)
    adapter = args.first

    unless adapter.kind_of?(Adapters::AbstractAdapter)
      adapter = Adapters.new(*args)
    end

    Repository.adapters[adapter.name] = adapter
  end

args は可変長引数なので Array インスタンスである.setup メソッドの呼び出し方が

DataMapper.setup(:default, 'mysql://localhost/dm_test')
DataMapper.setup(:default, {
  :adapter  => 'postgres',
  :database => 'localhost/dm_test',
  ...
})

であることから,ローカル変数 adapter はコンテキスト (Repository) を識別するための Symbol が入る.adapter が AbstractAdapter 派生のインスタンスでなければ (←通常は Symbol なのでこのパターン),引数 args から新しい Adapter を作成する (MysqlAdapter 等).Adapters.new メソッド内部では,以前紹介した DataMapper.setup メソッドのように uri/Hash から Adapter インスタンスを作成しているが,このコードがまたきれいにまとめられていて,とても読みやすい (Adapters についてはまた今度).

最後は name を key として Adapter インスタンスが Repository.adapters に蓄えられる.adapter.name は,setup メソッドの第 1 引数に渡した Symbol である.

ところで,adapter.kind_of? で AbstractAdapter かどうかを見ているということは,setup メソッドの引数に Adapter インスタンスが渡せるということか?

DataMapper.repository

このメソッドはあまり変わっていない.ただ,コードが整理され,すっきりしてる.

module DataMapper
  def self.repository(name = nil)
    context = Repository.context

    current_repository = if name
      assert_kind_of 'name', name, Symbol
      context.detect { |repository| repository.name == name }
    else
      name = Repository.default_name
      context.last
    end

    current_repository ||= Repository.new(name)

    if block_given?
      current_repository.scope { |*block_args| yield(*block_args) }
    else
      current_repository
    end
  end

基本的な流れは以下の通り.

  1. context (コンテキストスタック) を取得
  2. 引数に name が指定されていれば,context から名前の一致する Repository インスタンスを取得
  3. 引数に name が指定されていなければ,:default を name とし,context から末尾の Repository インスタンスを取得
  4. context から Repository インスタンスがとれなかった (nil だった) 場合は,新しい Repository インスタンスを生成
  5. block が渡されていれば,block 渡して Repository#scope を呼び出す
  6. block が渡されていなければ,そのまま Repository インスタンスを返す

block 有りの呼び出しは,以下のようにコンテキストを明示して呼び出す際に用いる.

p = DataMapper.repository(:hoge) { Person.first }

block 無しの呼び出しは,主にモデルメソッドの内部におけるコンテキスト取得に用いられる.


Repository.context メソッドは,スレッドローカルから Repository インスタンスの配列 (コンテキストスタック) を取り出す.

module DataMapper
  class Repository
    def self.context
      Thread.current[:dm_repository_contexts] ||= []
    end

Repository#scope メソッドは,Repository.context の返すコンテキストスタックに self を積み,渡された block を実行する.

module DataMapper
  class Repository
    def scope
      context = Repository.context

      context << self

      begin
        yield self
      ensure
        context.pop
      end
    end

これは,yield で実行されるブロックの内部において,モデルメソッドの呼び出しで context 取得が行われた際に,正しい context を返すための処置である.

モジュール/クラス間の関係

無理矢理書いたのでおかしいかも.

DataMapper 0.10.2 Reading (その 1: パッケージ)

今回から 0.10.2 のコードへ突入.
その前に,0.9.11 のコードを読み進めたときの反省点.

  1. 全体像の把握をきちんとしていなかった
    • 気づいたら深さ優先になってた
  2. 図がない!
    • 自分で読み返してもわかりづらい!

と,いうわけで,気をつけろよ!>自分

パッケージ

  • dm-core
    • コアパッケージ.DataMapper の基本的な機能が含まれる.DataMapper::Resource とかはここに入ってる.
  • do
    • Database Driver 集.DataObjects モジュールとして interface が定義されている.do_mysql や do_sqlite3 等はここに含まれている.
  • dm-more
    • DataMapper の拡張機能とか,その他いろいろ含まれている.dm-aggregates とか dm-validations はここに入ってる.Rails 上で DataMapper 使うためのパッケージもここ.あ,なんか "dm-rest-adapter" ってのもあるみたい.(以下引用)
Extra, non-essential parts for DataMapper
Including
  * Migrations
  * Validations
  * Serializers
  * A Command-Line Interface
  * Timestamps
  * Types
  * ActiveRecord-style finders
  * Adapters for your favorite repository or database type
  * Integration with your favorite web frameworks
  * Observers for watching resources.
  • extlib
    • サポートライブラリ.主に ruby 標準クラスの拡張が含まれている.lazy_array とかはここに入ってる.
  • data_mapper
    • よく使われるパッケージを一括して require.
      • dm-core
      • dm-aggregates
      • dm-constraints
      • dm-migrations
      • dm-serializer
      • dm-timestamps
      • dm-validations
      • dm-types