【问题标题】:SQL How to get only 1 true valueSQL如何只获得1个真值
【发布时间】:2020-06-11 19:58:53
【问题描述】:

我正在构建一个应用程序,我需要能够唱主唱 我需要防止 2 位老师共享特定班级的领导头衔

class CreateClassroomTeachers < ActiveRecord::Migration[5.2]
  def change
    create_table :classroom_teachers do |t|
      t.belongs_to :classroom
      t.belongs_to :teacher
      t.boolean    :lead, default: false
    end
    add_index :household_people, [:classroom_id, :teacher_id], unique: true
    # Only one teacher in a classroom can be lead 
  end
end

我的模型中有这个

class ClassroomTeacher < ApplicationRecord
  belongs_to :classroom
  belongs_to :teacher


  validate :only_one_is_lead_teacher

  def only_one_is_lead_teacher
    if lead
      if ClassroomTeacher.where(classroom_id: classroom_id, lead: true).count > 0
        errors.add(:lead, "There can only be one (1) lead teacher per classroom")
      end
    end
  end
end

这方面的问题是,在创建时我可以让 2 位或更多位老师担任领导

感谢您的帮助

【问题讨论】:

  • 一个老师可以带两个班吗?
  • 是的 1 位老师可以带领 100 节课
  • 你能解释一下吗:问题是在 Create 上我可以让 2 位或更多的老师担任领导。目前的状况检查对我来说看起来不错,因为将停止为每个教室创建多个潜在客户。
  • 如果铅的目的是什么?条件检查,这个值在哪里定义。
  • 每个教室只能有 1 位教师担任领导。您有领导和 2 或 3 位教师的帮助。但只有 1 人可以担任主讲老师。我有铅 t.boolean :lead, default: false 的布尔值,但我不知道怎么说只有 1 可以是铅

标签: ruby-on-rails pg


【解决方案1】:

有几种方法可以通过约束、触发器等来实现这一点 - 取决于您各自的数据库服务器支持什么。

应该至少在 Postgres 中起作用(即使它可能有点 hacky)是在 %i[classroom_id lead] 上设置唯一索引并确保 leadtrue 或 @ 987654324@。这应该可行,因为 Postgres 将 NULL 值视为不同的,这意味着如果多个 NULL 值存储在具有唯一性约束的列中,它不会报错。


如果您想在代码中解决它(我个人不建议这样做,因为您的数据库可能会被您的代码以外的东西访问,甚至您的代码也可以解决它,例如直接写入数据库而不是使用ActiveRecord 的高级方法),这是我过去的做法:

class ClassroomTeacher < ActiveRecord::Base
  before_save :ensure_only_one_lead_teacher

  private

  def ensure_only_one_lead_teacher
    # We don't have to do this unless the record is the one who should be the (new) lead.
    return unless lead?

    # Set all other records for the class room to lead = false.
    self.class.where(classroom_id: classroom_id).update_all(lead: false)

    # Now if the record gets persisted, it will be the only one with lead = true.
  end
end

一个可能稍微“正确”的方法是在记录被持久化后确保唯一性:

class ClassroomTeacher < ActiveRecord::Base
  after_commit :ensure_only_one_lead_teacher

  private

  def ensure_only_one_lead_teacher
    # We don't have to do this unless the record is the one who should be the (new) lead.
    return unless lead?

    # Set all other records for the class room to lead = false. Note that we now have to exclude
    # the record itself by id because it has already been saved.
    self.class.where.not(id: id).where(classroom_id: classroom_id).update_all(lead: false)
  end
end

【讨论】:

  • 谢谢,这真的很有帮助
【解决方案2】:

根据迁移,模型的属性是 ClassroomTeacher:classroom_id、teacher_id、lead

考虑将教师添加到课堂:

/控制器文件

def create
  ClassroomTeacher.create(teacher_id: data1, classroom_id: data2, lead: data3)
end

具有理想值的可能样本数据是:

id classroom_id teacher_id lead
1     1             3       false
2     2             4       true
3     1             2       false
4     1             5       true

现在您需要避免任何新教师被添加到课堂作为领导。模型验证代码可以是

validate :only_one_is_lead_teacher

def only_one_is_lead_teacher
  if self.lead
    class_obj = ClassroomTeacher.where(classroom_id: self.classroom_id, lead: true).first
    if class_obj.present?
      self.errors.add(:lead, "There can only be one (1) lead teacher per classroom")
      return false
    end
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 2022-07-31
    • 1970-01-01
    相关资源
    最近更新 更多