2017-04-18 1 views
1

は、私はそれぞれの本は本を読まされたかどうかを示すboolean変数readを持つことになり、二つのクラスRailsの一対多:フィールドの値を検証

class student < ApplicationRecord 
     has_many :books 
    end 

    class Book < ApplicationRecord 
     belongs_to :student 
    end 

があるとします。各生徒は1冊の本しか読むことができません。生徒の本のいずれかが読まれたとマークされている場合、他の本はもう読めません。

この制約が発生するためのPSQLまたはアクティブレコードの検証はありますか?

具体的には、book.update_attributes!(read: true)は他の関連書籍のチェックを行います。 DB制約がより好ましい。

多くの感謝!問題文の

更新:

読み取りは、タイムスタンプread_atになり、生徒は以前、他の本を読んでいる場合book.update_attributes!(read_at: Time.zone.now)は、チェックを行います。ブックモデルで

+0

とき意志が働くユニークな検証を追加ブックテーブルにレコードが作成され、 'read'が' false'に設定され、そのブックが読み込まれると 'true'に更新されます。一旦ブックが読み込まれると、別のブックの' read '真になるまでの価値は失敗するはずです。起立? – skwidbreth

+0

書籍は既定の読み取りfalseで作成され、読み取るとtrueに更新されます。同じ生徒の読み取り値の異なる書籍を真に変更しようとすると、失敗するはずです – LOCKLOCK

答えて

1

真の読み取りが同じでユニークな部分ブールreadフィールドにインデックスと整数student_idフィールドを追加します

add_column :books, :read, :boolean, null: false, default: false 
add_index :books, [:student_id, :read], unique: true, where: "read=true" 

だから、ときにのみbook.read == true

validates :read, uniqueness: { scope: :student_id }, if: -> (book) { book.read } 
+0

これにより、一意性が検証されます。 allow_falseがあるかどうか知っていますか:trueとallow_nil:true? – LOCKLOCK

+0

はい、そうです。私は私の答えを更新し、それをテストしました。 –

+0

'validate:読み取り、一意性:{スコープ::student_id}、if: 'read.present?''これも同様に動作します。 – LOCKLOCK

関連する問題