可以模拟“belongs_to”两个其他模型并具有嵌套关系?

时间:2010-08-03 23:27:43

标签: ruby-on-rails

模型是否可以属于,两个模型并具有嵌套关系?

即我想要的东西

class trainer
has_many :appointments
end

class appointment
belong_to :trainer, :customer
end

class customer
has_many :appointments
end

目前我只有客户和预约模型,例如我拥有的内容:

create方法如下所示:

  def create
    @appointment = @customer.appointments.build(params[:appointment])

    respond_to do |format|
      if @appointment.save
        format.html { redirect_to([@customer, @appointment], :notice => 'Appointment was successfully created.') }
        format.xml  { render :xml => @appointment, :status => :created, :location => @appointment }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @appointment.errors, :status => :unprocessable_entity }
      end
    end
  end

在我的路线中:

  map.resources :patients, :has_many => [ :appointments, :visits ]

1个模型可以有2个嵌套关系吗?如果约会也属于培训师和客户,我还需要改变我的创建方法吗?

谢谢

1 个答案:

答案 0 :(得分:21)

假设您正在使用ActiveRecord:当然可以使模型属于多个其他模型(但是您需要为每个关系指定一个belongs_to语句)。

class Appointment < ActiveRecord::Base
  belongs_to :trainer
  belongs_to :customer
end

belongs_to关系并不一定意味着该记录实际上与其他记录有关;它也可以是零。因此,您可以拥有属于培训师的约会但没有客户,反之亦然。

实际上,您甚至既没有培训师也没有客户,或者既没有培训师也没有客户 - 如果这违反了您的业务逻辑,您可能需要添加验证来防止这种情况发生。

您现有的控制器创建方法应该继续按原样运行,您只需要添加训练记录的处理。您甚至可以通过抽象培训师和客户来使用相同的控制器来处理培训师和客户的预约,例如成为这样的人:

class AppointmentsController < ApplicationController

  def create
    @appointment = person.appointments.build(params[:appointment])
    # ...
  end

protected

  def person
    @person ||=
      if params[:trainer_id]
        Trainer.find(params[:trainer_id])
      elsif params[:customer_id]
        Customer.find(params[:customer_id])
      end
  end
end

这样,您可以为两个路径使用相同的AppointmentsController

# Use AppointmentsController for /trainers/123/appointments
# as well as for /customers/123/appointments
map.resources :trainers, :has_many => :appointments
map.resources :customers, :has_many => :appointments

当然,只有教练任命和客户约会背后的逻辑和观点几乎相同,这才有意义。如果没有,您也可以使用不同的控制器

# Use TrainerAppointmentsController for /trainers/123/appointments and
# CustomerAppointmentsController for /customers/123/appointments
map.resources :trainers do |trainer|
  trainer.resources :appointments, :controller => 'trainer_appointments'
end
map.resources :customers do |customer|
  customer.resources :appointments, :controller => 'customer_appointments'
end