Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor validates_uniqueness_to_tenant #242

Merged
merged 2 commits into from
Dec 16, 2020

Conversation

artplan1
Copy link
Contributor

Hi,
I refactored this validation method because it didn't work for global records with mobility. Queries used in validates_uniqueness_to_tenant didn't work with mobility's fields.
But mobility overrides UniquenessValidator to validate translated fields.

I decided to use validates_uniqueness_of in the case of global model, because validates_uniqueness_of runs same query by itself.

For global records:

  • In 1st validates_uniqueness_of we're validating uniqueness in tenant (query: tenant = value)
  • in 2nd validates_uniqueness_of we're validating global uniqueness (query: tenant = nil)

in perfect world it should be done with 1 query validating tenant = nil OR value, but rails validations don't allow it.

@artplan1 artplan1 force-pushed the refactor-uniqueness-validation branch 2 times, most recently from 9e7eae5 to 13eaaf8 Compare December 10, 2020 15:15
@artplan1 artplan1 force-pushed the refactor-uniqueness-validation branch from 13eaaf8 to 47d6f24 Compare December 10, 2020 15:31
.where.not(id: instance.id).empty?
errors.add(field, "has already been taken")
end
global_validation_args = args.merge(conditions: -> { where(fkey => nil) })
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this, because it discards conditions from args, not sure how to merge lambdas here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only thing I could imagine working for that would be an array of lambdas?

@artplan1 artplan1 marked this pull request as draft December 10, 2020 16:02
@artplan1 artplan1 force-pushed the refactor-uniqueness-validation branch from 64e60bf to f561199 Compare December 10, 2020 18:02
@artplan1 artplan1 force-pushed the refactor-uniqueness-validation branch from f561199 to 18f764b Compare December 10, 2020 18:19
@artplan1
Copy link
Contributor Author

artplan1 commented Dec 10, 2020

hi again @excid3 ,
while trying to figure out what is wrong in our codebase I found out one more case that wasn't covered in validations/tests here:
when user is trying to create global record, but record with same name exist in some tenant.

I splitted validations to 3:

  1. validate within tenant scope (old validation that is working and is correct)
  2. if model is global and tenant is not set on instance - validating globally (tenant id can be nil or filled)
    1st validation doesn't cover this, because when tenant is set it filters within tenant, if it's not set it filters within nil. But we need to search within all records if current record is global
  3. if model is global and tenant is set on instance - validating within global records (searching non-unique records with tenant id = nil)
    1st validation covers half of this, because when tenant is set it filters within tenant, if it's not set it filters within nil. But we need to search within records with tenant = nil or tenant = current (covered by 1st) if current record has tenant = current
    2nd doesn't cover this we need scoping

Also I've added calls for conditions and if if they are passed to validates_uniqueness_to_tenant

Also I think if ActsAsTenant.models_with_global_records.include?(self) is redundant here. If record is not global - it shouldn't have empty tenant in this validation. This way we can reduce number of validations by adding if: ->(instance) { instance[fkey].present? } to 1st one, because it only makes sense if tenant is set

@artplan1 artplan1 marked this pull request as ready for review December 10, 2020 18:21
@excid3
Copy link
Collaborator

excid3 commented Dec 10, 2020

I think this sounds good. I haven't used any global models like this in an app so I'll have to refresh myself on it.

Could any of these changes be breaking for existing users?

@artplan1
Copy link
Contributor Author

Could any of these changes be breaking for existing users?

I hope no

  1. I think small percentage of gem users use global records
  2. tests are green
  3. tests are green in our project with changes from my branch :D

Copy link

@dmc0re dmc0re left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, plz 🚢 it

@excid3 excid3 merged commit 10ea994 into ErwinM:master Dec 16, 2020
@artplan1 artplan1 deleted the refactor-uniqueness-validation branch December 16, 2020 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants