0

我目前有两个模型作为 STI。

class Event
class BlockedTime < Event
class Appointment < Event

这些模型是相似的,除了 'Appointment' has_one 'client' 和 has_one 'service',而 'BlockedTime' 没有这些关联。

此外,我希望能够轻松地在这两种类型之间进行转换,当我搜索时,我通常会同时搜索两种类型,而不是其中一种。出于这些原因,我犹豫将它们分成单独的表格。

为了在类型之间切换,我目前以相同的形式执行此操作,使用父“事件”类型,并将“类型”存储为隐藏字段,但这绝对不是很好。我必须在控制器中进行各种转换以检查验证等。

你会如何推荐这个建模?

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在此表单中包含所有字段。您可能想根据radio_button选择编写一些 javascript 来禁用/启用字段

于 2012-05-28T22:58:12.160 回答