【问题标题】:Only one record true, all others false, in rails在rails中只有一个记录是真的,其他的都是假的
【发布时间】:2009-10-11 09:12:00
【问题描述】:

我有以下情况

class RecordA
  has_many :recordbs
end

class RecordB
  belongs_to :recorda
end

RecordA 有许多recordb,但只有一个可能是活动的recordb。我需要类似myRecordA.active_recordb

如果我将is_active 这样的新列添加到RecordB,那么我可能会同时将两条记录设置为is_active = true

我可以使用哪种设计模式?

谢谢!

【问题讨论】:

  • 最好使用真实的模型名称而不是“RecordA”和“RecordB”,帮助人们思考你的想法,

标签: ruby-on-rails design-patterns model has-many


【解决方案1】:

让我们改变你的例子。有一个LectureRoom,有很多人,只有一个人可以担任讲师。

在 LectureRoom 中有一个属性来指示哪个 Person 是讲师会容易得多。这样,您无需更改多个人员记录即可更换讲师。您只需要更新 LectureRoom 记录。

【讨论】:

    【解决方案2】:

    我会使用命名范围来查找当前讲师。

    class Person
      named_scope :currently_speaking, :conditions => {:active => true}
    end
    

    那我就称他为 ClassRoom 的讲师:

    class ClassRoom
      def lecturer
        people.currently_speaking.first
      end
    end
    

    真正的问题是确保当您激活其他人时,他们会成为唯一活跃的人。我可能会这样做:

    class Person
      belongs_to :class_room
    
      before_save :ensure_one_lecturer
    
      def activate!
        self.active = true
        save
      end
    
      def ensure_one_lecturer
        if self.active && changed.has_key?(:active)
          class_room.lecturer.update_attribute(:active, false)
        end
      end
    
    end
    

    这样,一切都在事务中完成,只有在您更改了活动状态时才会完成,并且应该很容易测试(我还没有测试过)。

    【讨论】:

    • 另外,我应该补充一点,您可能需要在执行此操作时在人员表上使用锁,否则您可能会在激活人员时看到竞争条件。
    【解决方案3】:

    您可以为此在 RecordB 上定义一个类方法:

    class RecordB < ActiveRecord::Base
      def self.active
        first(:conditions => { :active => true }
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2021-06-29
      • 1970-01-01
      • 1970-01-01
      • 2015-07-25
      • 1970-01-01
      • 2013-06-11
      • 2013-05-02
      • 1970-01-01
      • 2013-05-28
      相关资源
      最近更新 更多