对关联对象的验证在创建和更新时的行为方式不同

时间:2016-11-29 07:11:57

标签: ruby-on-rails validation associations

我遇到了一个自定义验证问题,它会检查关联对象的数量。有两个类,EventGuest

当用户创建新活动时,他可以选择一些邀请的来宾。保存后,我想检查一下受邀嘉宾的数量。

更新现有事件时,验证工作正常。但是在创建新事件时,验证失败,因为self.guests.count返回0。 在控制器中,我检查了所选的客人是否以相同的方式传递给模型:params[:event][:guest_ids]

如果发生更新,我可以看到在调用验证块之前,更新关联表的SQL INSERT INTO被添加到事务队列中。但是在新事件的情况下,SQL INSERT在验证失败之前不会显示。

我在这里缺少什么?我正在考虑一些解决方法,但我确信有一种正确的方法来实现它。

Rails版本是4.2.6

class Event < ActiveRecord::Base
  has_and_belongs_to_many :guests
  validate :check_guestlist

  def check_guestlist
    guest_count=self.guests.count
    if guest_count < 3
      errors.add(“Please invite more guests”)
    end
  end

class Guest < ActiveRecord::Base
  has_and_belongs_to_many :events
end


class EventsController < ApplicationController
  def create
    @event = current_user.events.new(event_params)

    respond_to do |format|
      if @event.save
        format.html { redirect_to @event, notice: 'Event was successfully created.' }
      else
        flash.now[:alert]='Event not saved.'
        format.html { render action: "new" }
      end
    end
  end

  def update
    @event = current_user.events.find(params[:id])

    respond_to do |format|
      if @event.update_attributes(event_params)
        format.html { redirect_to @event, notice: 'Event was successfully updated.' }
      else
        flash.now[:alert]='Changes not saved.'
        format.html { render action: "edit" }
      end
    end
  end
end

2 个答案:

答案 0 :(得分:0)

我设法通过替换自定义验证中的一行代码来解决此问题。 如果我更换

    guest_count=self.guests.count

    guest_count=self.guests.to_a.count

我得到了预期的结果。 在更新的情况下,两个表达式都返回相同的结果。但是在新记录的背景下,只有第二个响应预期。 不过,我仍然不明白为什么第一个版本没有用。

答案 1 :(得分:0)

好的,self.guests.count在创建时不起作用的原因是这实际上是在进行数据库查询,具有事件范围。

SELECT COUNT(*) FROM {客人{1}} {客人{1}}的event_id WHERE

现在当然失败了,因为验证发生在客人保存之前。现在更新它是有效的,因为在数据库中有条目。但是,验证是检查错误的信息 - 数据库中的访客数量不一定与self.guests的数量相匹配 - 您可以添加一个尚未保存的访客。

您的解决方案确实有效,但我个人认为最好将其编写为:

.

= 1将测试来宾数组的大小 - 例如validates :guests, length: { minimum: 3, message: 'Please invite more guests' } 实际上与length

相同