0

現在STIとして所有しているモデルが2台あります。

class Event
class BlockedTime < Event
class Appointment < Event

モデルは、'Appointment' has_one 'client' と has_one 'service' を除いて類似していますが、'BlockedTime' にはこれらの関連付けのいずれもありません。

さらに、2 つのタイプを簡単に変換できるようにしたいので、検索するときは通常、どちらか一方ではなく、両方のタイプを一緒に検索します。これらの理由から、私はそれらを別々の表にすることをためらっています。

タイプを切り替えるには、現在、親の「イベント」タイプを使用し、「タイプ」を非表示フィールドとして保存する同じフォームでこれを行っていますが、これは明らかにうまくいきません。検証などを確認するために、コントローラーであらゆる種類の変換を行う必要があります。

これをどのようにモデル化することをお勧めしますか?

4

1 に答える 1

1

したがって、この問題が発生した場合は、おそらくデータベースを別の方法でモデル化するでしょう。

STI/継承パターンの代わりに、コンポジションパターンを使用します。そう:

class Appointment
  belongs_to :block_time, :class_name => "BlockTime"
  ...
end

class BlockTime
   has_one :appointment
   accepts_nested_attributes_for :appointment, :allow_destroy => :true, 
                                               :reject_if => :all_blank

  ...
end

コントローラ

class AppointmentsController < ApplicationController
  ...

  def new
    @block_time = BlockTime.new
    @block_time.appointment or @block_time.build_appointment
    ...
  end

  def edit
    @block_time = BlockTime.includes(:appointment).find(params[:id])
    @block_time.appointment or @block_time.build_appointment
  end

  ...
end

フォームまたは少なくともフォームの一部

<%= f.fields_for :appointment do |g| %>
  <div>
    <%= g.radio_button :_destroy, "1", :checked => !g.object.persisted? %>
    <%= g.label :_destroy_1, "Has no Appointment" %>

    <%= g.radio_button :_destroy, "0", :checked => g.object.persisted? %>
    <%= g.label :_destroy_0, "Has Appointment" %>
  </div>

  <p>
    Client: <%= g.text_field :client %>
  </p>
<% end %>

フォームのこの部分は、オブジェクトが新しいレコードであるか、データベースに永続化されているかpersisted?を確認するために使用します。Appointment次に、それを削除したい場合は、_destroyフラグをスローしaccepts_nested_attributes_forて既存のappointment関連付けを削除し、 free にしBlockTimeます。

次に、このフォームにもすべてのAppointmentフィールドを含めることができます。選択に応じてフィールドを無効/有効にするために、いくつかのJavaScriptを作成することをお勧めしますradio_button

于 2012-05-28T22:58:12.160 に答える