DataMapperでTwoWaySQLを簡単に使うためのdm-twowaysqlってのを作ってみた。

RailsでDataMapperを使っている人て少ないと思う。Railsを使う場合は大抵新規プロジェクトだから。 でも、世の中そんな簡単じゃなくて、既に動いているDBをRailsで触る必要だってある。例えば次のようなDB。

  • 主キーが文字列だったり日付
  • 複合主キー
  • 主キーの名前がばらばら
  • Oracleなので名前に変な略語が、、

ActiveRecordでは難しいテーブルもDataMapperだったらさっくり扱える。そのあたりはこの資料が詳しい。

動いているDBを触るときはDataMapperが最強だな!と思うわけだけど、DataMapperには生のSQLをうまく扱うためのライブラリがなかったりする。 サブクエリをガリガリ書いたり、unionしなくちゃいけない場合、ちょっとつらい。

ちょっと調べてみて、S2DaoS2JDBCの2Way SQLrubyで扱うライブラリ TwoWaySQL が 使えれば良いのでは?と思ってdm-twowaysqlってのを作ってみた。

でっち上げなのでテストとか適当。

インストール

Gemfile に

gem 'dm-twowaysql', '~> 0.1.0'

もしくは

$ gem install dm-twowaysql

使い方

class PersonGateway
  # DataMapper::Resourceをインクルードしてなくても使える。
  include DataMapper::TwoWaySQL

  # template_select_person_index_page と select_person_index_page が定義される
  twowaysql :select, :person_index_page, <<-EOS
    SELECT * FROM people
    /*BEGIN*/WHERE
      /*IF ctx[:name]*/ name = /*ctx[:name]*/'Bob' /*END*/
      /*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK' /*END*/
      /*IF ctx[:age]*/ AND age > /*ctx[:age]*/30 /*END*/
    /*END*/
    /*IF ctx[:order_by] */ ORDER BY /*$ctx[:order_by]*/id /*$ctx[:order]*/ASC /*END*/
  EOS

  # template_execute_update_all_name と execute_update_all_name が定義される
  twowaysql :execute, :update_all_name, <<-EOS
    UPDATE people SET name = /*ctx[:name]*/'name'
  EOS
end

PersonGateway.template_select_person_index_page # => TwoWaySQL::Template instance
PersonGateway.template_execute_update_all_name  # => TwoWaySQL::Template instance

# merged = PersonGateway.template_select_person_index_page.merge({})
# ::DataMapper.repository(:default).adapter.select(merged.sql, *merged.bound_variables)
PersonGateway.select_person_index_page(:default, {})

# merged = PersonGateway.template_execute_update_all_name.merge({:name => 'jobs'})
# ::DataMapper.repository(:default).adapter.execute(merged.sql, *merged.bound_variables)
PersonGateway.execute_update_all_name(:default, {:name => 'jobs'})