1

I have a 1-to-1 association between 2 mongoid models and I keep getting duplicates, that is having more than one child record(card) with same parent_id(that is user). I have tried validating uniqueness of the belongs_to association has shown below, but it doesn't work.

 class User
   include Mongoid::Document
   field :name, type: String 
   has_one :card
 end

The second model:

 class Card
   include Mongoid::Document
   field :name, type: String 
   belongs_to :user

   validates :user, :uniqueness => {:scope => :user_has_child}

   def user_has_child
     q = Segment.where(drop_id: {'$ne' =>  nil})
     s = q.map(&:drop_id)
     errors.add(:drop_id, "this user already has a card") if s.include?(:drop_id)
   end

 end
brg
  • 3,915
  • 8
  • 37
  • 66
  • I don't understand why you need something more complicated than `validates_uniqueness_of :user_id` ? (Or just `user` should work too I think) – Cyril Duchon-Doris Aug 04 '15 at 17:06
  • Thanks you are correct. I had tried that before and it didn't seem to work. But when you suggested it, I tried it again and it failed then I realized I needed to reload the data to see that it didn't save to database even though the in memory copy is still showing the wrong record that didn't save to db. – brg Aug 04 '15 at 17:27
  • Cool. I made an answer with more details that you can upvote and accept ;-) – Cyril Duchon-Doris Aug 04 '15 at 23:23

1 Answers1

2

The syntax is more simple. You just want to make sure there are no 2 documents with the same user_id

class Card
  belongs_to :user

  validates_uniqueness_of :user

You need to use scope if you want the uniqueness of a tuple of n fields. For example, if a User can have at most one card per year, you can write

class Card
 field :year
 belongs_to :user  

 validates_uniqueness_of :user, scope: [:year] # A user can have one card per year

Note that validations apply when you save the model ie. you try to persist the changes. Calling .save will return true or false if some validations fail, but the object in memory is always modified! This is so, for example, you can display previous values in the HTML input fields, so the user knew what he wrote and can fix it (otherwise he'd have to re-write all his information in case of a single mistake)

Also, Mongoid by default handles dirty tracking (this is now the doc for v5.0 but it was the same for Mongoid 4). That is to say, you can call .changed? .changes, etc on the object in memory to see what are the changes compared to the object in the DB.

Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164