#ruby-on-rails
#ruby-on-rails
Вопрос:
namespace :send_query do
task :to_admins => :environment do
contacts = Contact.select(:name, :mobile, :company, :requirement).where(email_sent: false).distinct
if !contacts.blank?
contacts.each do |contact|
GuestMailer.query_email(contact.name,
contact.mobile,
contact.company,
contact.requirement).deliver
contact.update!(email_sent: true)
end
end
puts "done sending query emails"
end
end
Я написал задачу rake для отправки электронных писем. После отправки электронной почты я обновляю поле email_sent на true. Но транзакция откатывается после отправки электронной почты.
(0.2ms) BEGIN
Contact Exists (0.7ms) SELECT 1 AS one FROM "contacts" WHERE "contacts"."name" = $1 AND ("contacts"."id" IS NOT NULL) AND "contacts"."mobile" = $2 AND "contacts"."requirement" = $3 AND "contacts"."company" = $4 LIMIT $5 [["name", "vamsi pavan mahesh"], ["mobile", "9247474925"], ["requirement", "yo yo honey singhu"], ["company", "mahesh@bla.com"], ["LIMIT", 1]]
(0.2ms) ROLLBACK
rake aborted!
ActiveRecord::RecordInvalid: Validation failed: Name has already been taken
Вот модель контакта
# == Schema Information
#
# Table name: contacts
#
# id :integer not null, primary key
# name :string
# mobile :string
# company :string
# requirement :text
# created_at :datetime not null
# updated_at :datetime not null
# email_sent :boolean default(FALSE)
#
class Contact < ApplicationRecord
validates :name, presence: true
validates :mobile, presence: true
validates :requirement, presence: true
validates_uniqueness_of :name, scope: [:mobile, :requirement, :company]
end
Комментарии:
1. чтобы обойти проверку, вы можете сделать
contact.update_attribute(:email_sent, true)
2. я хочу проверку! не могли бы вы перечитать вопрос
3. Это то, что мне не нравится в проверках: после того, как вы сохранили свою запись, и через некоторое время вы добавляете другую проверку, и эта старая запись не может пройти эту проверку, вы больше не сможете ее обновлять, даже если вы не измените атрибут, из-за которого проверка завершается неудачно. Обходной путь для его использования — использовать
if
условие проверки:validates :name, uniqueness: { scope: [:mobile, :requirement, :company] }, if: 'self.name_changed?'
4. @AndreyDeineko обход проверки следует выполнять только в очень редких случаях. Особенно не в задаче rake, которая предназначена для запуска время от времени
5. @MrYoshiji согласен, я не думаю, что обход проверки вообще приемлем (или, как вы говорите, очень редко). Иначе зачем это? 🙂
Ответ №1:
В вашей Contact
модели вы можете сделать on: :create
, и это будет применяться только для проверки действия create.
validates :name, presence: true, on: :create
Редактировать:
Как указал MrYoshiji в комментариях, именно uniqueness
проверка имени вызывает ошибку проверки, поэтому исправление на самом деле будет:
validates :name, uniqueness: { scope: [:mobile, :requirement, :company] }, on: :create
Комментарии:
1. Я думаю, вы имели
validates :name, uniqueness: { scope: [:mobile, :requirement, :company] }, on: :create
в виду, что неудачная проверка связана с уникальностью имени, а не с наличием имени.2. Ах, да, это правильно. Я обновлю свой ответ на то, что сказал MrYoshiji.
3. Я думаю, что это ненадежно. Если мы применим что-то к on: :create. Уже созданная запись может быть обновлена, чтобы иметь повторяющееся имя при ее обновлении