ActiveRecord: можно ли добавлять объекты в has_many: through в одной пакетной операции? - PullRequest
2 голосов
/ 22 августа 2009

Возьмем следующую простую объектную модель, например:

class Course
  has_many :enrollments
  has_many :students, :through => :enrollments, :after_add => :send_email

  def send_email(student)
    puts "Email Sent"
  end
end

class Enrollment
  belongs_to :course
  belongs_to :student
end

class Student
  has_many :enrollments
  has_many :courses, :through => :enrollments
end

Я хотел бы выполнить send_email после добавления одного или нескольких студентов в курс, однако after_add запускается после добавления каждого элемента в коллекцию студентов.

bill = Student.first
carl = Student.last

Course.first.students << [bill, carl]

Будет выводить

Email Sent
Email Sent

Как я могу поймать одно событие после того, как ВСЕ элементы добавлены в коллекцию?

Можно ли вставить записи в таблицу enrollments в одном запросе для всех учащихся, а не по одному на каждого учащегося?

Есть ли в Rails какой-либо встроенный механизм или мне нужно написать собственную логику для перехвата, а затем вызовы пакетной очистки send_email?

Спасибо за любую информацию!

Ответы [ 3 ]

2 голосов
/ 09 октября 2009

Добавление обратного вызова after_create в модель регистрации приведет к желаемому поведению.

При пакетных назначениях в отношении has_many: through создаст записи в таблице регистрации по мере необходимости. Для каждой новой записи Rails будет применять все проверки и обратные вызовы в модели соединения. Если зачисление студента на курс отмечено записью в таблице зачисления зачислений. Тогда это сработает независимо от того, как вы добавите студента в курс.

Это код для изменения класса регистрации

class Enrollment < ActiveRecord::Base
  belongs_to :course
  belongs_to :student
  after_create :send_email

  protected
    def send_email
      course.send_email(student)
    end
end

Он будет вызывать подпрограмму send_email курса, если вы записали запись о регистрации с помощью Rails.

Следующие будут отправлять электронные письма.

@student.courses << @course
@course.students << @student
Enrollment.create :student => @student, :course => @course
0 голосов
/ 22 августа 2009

как насчет:

@last_student = Student.last

def send_email(student)
    put 'email sent' if student == @last_student
end

Может быть немного грязно использовать переменную экземпляра, но она должна работать.

0 голосов
/ 22 августа 2009

Я проверил, и похоже, что ни один из встроенных обратных вызовов не сделает то, что вам нужно. Вы можете поэкспериментировать с пользовательскими классами обратного вызова, чтобы увидеть, сможете ли вы достичь того, что вам нужно.

http://guides.rubyonrails.org/activerecord_validations_callbacks.html#callback-classes

Удачи:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...