Может ли модель "принадлежать" двум другим моделям и иметь вложенные отношения? - PullRequest
10 голосов
/ 04 августа 2010

Возможно ли, чтобы модель принадлежала двум моделям и имела вложенные отношения?

то есть то, что я хочу

class trainer
has_many :appointments
end

class appointment
belong_to :trainer, :customer
end

class customer
has_many :appointments
end

на данный момент у меня есть только модели клиентов и встреч, которые вложены, например, в то, что есть у меня:

метод создания выглядит следующим образом:

  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 ]

возможно ли иметь 2 вложенных отношения для 1 модели? на что я должен изменить свой метод создания, если назначение также принадлежало как тренеру, так и клиенту?

спасибо

1 Ответ

22 голосов
/ 04 августа 2010

Предполагая, что вы используете ActiveRecord: конечно, возможно наличие модели, принадлежащей более чем к одной другой модели (однако для каждого отношения необходимо указать один оператор принадлежат_).

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

Отношение own_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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...