Uniqueness scope

HI,

I have a question about uniqueness scope. I have a Scale model with this fields group_id name min_val max_val category

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?

Thanks

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. :wink:

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 below....

-Dave

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

another

-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

http://stackoverflow.com/questions/5028612/reservation-type-system-w-validation-rails-3-0

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

end

but … is there a better way?

Thanks

Javier

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.

-Dave

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.