DEV Community

Cover image for Ensure only one record has specific value for another associated record | Rails 6.1.4
marelons1337
marelons1337

Posted on • Edited on • Originally published at blog.rafaljaroszewicz.com

Ensure only one record has specific value for another associated record | Rails 6.1.4

I couldn't come up with a better title, but for my app for landlords I faced a problem where I don't want to remove old tenants. I want to store them in a database for future reference. So that leaves me with problem of making sure that only one tenant can have "active" status at any given time.

Now, I tried to find a way of forcing that on a database level, but then I thought about rails validations. I can check that on adding or modifying my tenants. And since my app will never be big enough for multiple users to update the same record in DB concurrently, I decided to implement that directly in the app.


Let's assume our Flat has_many :tenants and Tenant belongs_to :flat

I will take advantage of rails model callback order. And first four go as below:

  1. before_validation
  2. after_validation
  3. before_save
  4. around_save

So now I can use this order to force validation of my record to see if any other tenants are active. If there is another tenant that is active, I won't allow the record to save. Sounds simple to me.

Few things happened above. I use my method determine_active in my validation. I do that because in my force_one_active function, it first checks if the tenant should be active at all, then performs a search to check if there are any additional tenants with the same status, if it happens to find that the flat is occupied, it stops the record from saving on a validation level, thus leaving active = false.

Works!

I've also added another function to set flat's taken value if our current tenant happened to be active.

Now, because this method is in before_save callback it will never run unless validation has passed successfully, as per order shown previously.

It's not perfect, but it works for a smaller scale app like mine.

Top comments (0)