トップ «前の日記(2006-12-15) 最新 次の日記(2006-12-18)» 編集

3 日坊主日記


2006-12-17 [長年日記]

_ [Rails] Temporal Data on Rails: #1 Collection Item の生成

妄想中。

Member モデルが複数の Child モデルを持つとき 単一の view で入力したい。

 <%-@member.children.each do |child|-%>
   <%= text_field "child", "nick", :index => child.id, :object => child %>
 <%-end-%>

前提: session, ActiveForm, Ajax を使わない。 タグヘルパを普通に使う。 確認画面が必要。 model は validation を行う。 view, controller を簡潔に書きたい。そのためのモデリングを考える。

課題:

  • A: :index に指定する id は save に成功しないと得られない。
  • B: 入力前に save すると validation に失敗する。

(対立項)

解法:

  • a: A を妥協。:index には each_with_index で得た順序値を指定する。-> create と update で :index の扱いが違うのが嫌。
  • b: B を妥協。validation しない。-> validation は必要。
  • c: validation を行う attr を別のモデルに置く (モデルを分割する)。-> 過激派。今回はこれ。
 class M   # Model
   attrs
   validates

次のように分割する。

 class TM  # Temporal Model
   has_one :ta
   # (id)
 class TA  # Temporal model's Attr model
   attrs
   validates

注意: M は残す。TM は Temporal Data (あるいは Historical Data) を保持。

課題: TM を M として扱うには TA 上の attrs を透過的に扱えるようにする必要がある。

  • reader
 tm.attr #=> tm.ta.attr
 def attr
   ta ? ta.attr : nil  # ta がないとき nil (ta を生成しない)
 end
  • writer
 tm.attr= #=> tm.ta.attr=
  • Q: TA はいつ生成&保存するのか。
  • A: tm.save する時。ただし attr が設定されたときのみ。
 def before_save
   if @attr
     ta.build
     ta.attr = @attr
     ta.save  #=> validation
 # after_save かも? has_one 先の save のタイミングを確認。
 # error_messages_for 指定はどうなる?
 def update_tmp
   @member = TmpMember.find(params[:id])
   @member.update_attributes(params[:member])
   params[:child].each do |id, attrs|
     @member.children.find(id).update_attributes(attrs)
 def confirm_update
   @member = TmpMember.find(params[:id])
 def update
   @member.commit  # tmp_member から member を生成; member.children も生成

以上を踏まえて acts_as_temporal_view プラグインを想像できる (Temporal Table の View の意)。

 class Member < ActiveRecord::Base
   acts_as_temporal_view
 class Child < ActiveRecord::Base
   acts_as_temporal_view
[]