Uniqueness scope


I have a question about uniqueness scope.
I have a Scale model with this fields

for example the first record will have as
- min_val : 0
- max_val : 10

and the next values shouldn't be in that range.

I discovered that I can do this....

validates :min_val, :uniqueness => { :scope => :group_id},

But I want to validate that the new min/max value is not in a already
saved record

Is there a rails way to do that?


Javier Q.

If I understand rightly, what you want to do is to divide the space up
into non-overlapping ranges. Is that correct? If so, then you could
use a validator function that checks the new record against all saved
records to see if there is overlap. That would be rather inefficient,
though, so if you're adding new Scales frequently, it could slow down
the system. If adding Scales is very rare, then remember the old
maxim: all algorithms are fast, for sufficiently small values of N.

Alternately, you could just forget about max and just record the min,
with the implied max being just below the min of the next group when
sorted by min. That would also ensure you have no holes, except below
the lowest min. However, that could be less efficient in usage
(finding the right range for a value) because you'd have to make sure
that not only is it above this min, but there are no higher mins it's


Yes I think is more a query problem than something of rails

I’ve already made a validation that won’t let a user to save this :

  • min_v : 10

  • max_v : 1

That validation was easy :slight_smile: , but (for example) what if I have this

-min_v : 0

-max_v :10


-min_v : 21

-max_v : 30

and then someone wants to save this

  • min_v : 8

  • max_v :25

I have to do some validation about it, I found this


def uniqueness_of_date_range

errors.add(:start_date, “not available”) unless Room.where("? >= start_date" AND ? <= end_date", start_date, start_date).count == 0

errors.add(:end_date, “not available”) unless Room.where("? >= start_date" AND ? <= end_date", end_date, end_date).count == 0


but … is there a better way?



Somewhat. That approach could add the same error twice. I'd probably do it as:

  errors.add(:start_date, "not available") unless
    (Room.where("? >= start_date AND ? <= end_date",
                start_date, start_date).count == 0 and
     Room.where("? >= start_date AND ? <= end_date",
                end_date, end_date).count == 0)

(Basically, instead of "error unless x" and then "same error unless
y", use "error unless x and y".)

Also I tend not to use "unless" very much; I don't think this
particular usage is any clearer than using "if" and checking whether
count > 0. But that's just a matter of personal style.

Other than that, yes, it's pretty much what I was thinking.


I just didn’t follow that code… because I wasn’t sure enough how would it handle the data,
by that I mean… how does rails know wich one is the data that is going to be validated and the data used for the validation,

I was searching and I guess the that a solution can be made with Proc.new

validates :minimun_value,

:uniqueness => {:scope=> [:group_id]},

:exclusion => { :in => Proc.new{|r| [(r.minimun_value)…(r.maximun_value)]}}

(the model Scale belongs_to Group, and Group has_many scales)

but nothing happens. I choose Proc.new because (as far as I understood) it let me go through the entire table, is that correct?

Javier Q.