Coder Social home page Coder Social logo

Comments (5)

tmock12 avatar tmock12 commented on September 13, 2024 9

For the reasons @rsmithlal mentioned, using scope is probably a bad idea. Thankfully validates_uniqueness_of comes with a conditions option. Using that I think you can achieve what you want with something like:

validates_uniqueness_of :email, conditions: -> { where(discarded_at: nil) }
# or:
validates :email, uniquess: { conditions: -> { where(discarded_at: nil) } }

This should only check uniqueness of emails on non 'deleted' (AKA discarded) records.

from discard.

pboling avatar pboling commented on September 13, 2024 6

@JamesDullaghan You can add an index to support the validation if you are using a nice database (PostgreSQL, MySQL...).

It would prevent undiscarding records though if there has been a conflicting record created, as @rsmithlal mentioned.

To insulate yourself from the potential craziness, you may want to have two unique indexes, ensuring you only ever have one discarded and one not discarded. It will depend on how you intend to use the data.

class AddUniquenessConstraint < ActiveRecord::Migration[5.2]
  def change
    add_index :users, %i[email], where: '(discarded_at IS NOT NULL)', name: 'idx_users_email_discarded_at_not_null'
    add_index :users, %i[email], where: '(discarded_at IS NULL)', name: 'idx_users_email_discarded_at_null'
  end
end

from discard.

rsmithlal avatar rsmithlal commented on September 13, 2024

It's possible that you would have to rework your uniqueness validator to capture information about the discarded_at column. I know that when defining one, you can pass a scope option, so that might be helpful.

One issue to be aware of with conditionally validating the uniqueness of your column for discarded and undiscarded records is that you might not be able to undiscard records if the column value is later used by another undiscarded record. For example, let's say that I have a discardable User class with a uniqueness validator on its email attribute. I scope the validator to some attribute that divides the set between discarded and undiscarded records. I create a user with the email [email protected]. I decide to discard that user record, and later someone else creates a user with the email [email protected]. I now have two User records in the system with the email [email protected], one discarded and one undiscarded. Because that attribute must be unique, I can no longer undiscard the original [email protected] user record.

Another issue with this approach might be that the value for the discarded_at column will almost always be a unique datetime, so you might have to add a boolean discarded column to your tables to use as your validator scope and set it using a before_discard callback. That way, your validator will check for a unique combination of each the column being validated and whether or not it has been discarded. This might not be ideal, but I suspect that it would work. If you do take this approach, be sure to define an callback for before_undiscard that reverses the value.

from discard.

jarednorman avatar jarednorman commented on September 13, 2024

I think Rails uniqueness validations should be skipped now, and as outlines above, the trick is to use a composite index that includes the discarded_at timestamp.

from discard.

jeffreycastro avatar jeffreycastro commented on September 13, 2024

@JamesDullaghan You can add an index to support the validation if you are using a nice database (PostgreSQL, MySQL...).

It would prevent undiscarding records though if there has been a conflicting record created, as @rsmithlal mentioned.

To insulate yourself from the potential craziness, you may want to have two unique indexes, ensuring you only ever have one discarded and one not discarded. It will depend on how you intend to use the data.

class AddUniquenessConstraint < ActiveRecord::Migration[5.2]
  def change
    add_index :users, %i[email], where: '(discarded_at IS NOT NULL)', name: 'idx_users_email_discarded_at_not_null'
    add_index :users, %i[email], where: '(discarded_at IS NULL)', name: 'idx_users_email_discarded_at_null'
  end
end

shouldn't there be a unique: true on the second index?

EDIT: oops didnt see the "It will depend on how you intend to use the data"

from discard.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.