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.

On Wed, Dec 14, 2011 at 12:06, JavierQQ [email protected] wrote:

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?

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


LOOKING FOR WORK! What: Ruby (on/off Rails), Python, other modern
languages.
Where: Northern Virginia, Washington DC (near Orange Line), and remote
work.
See: davearonson.com (main) * codosaur.us (code) * dare2xl.com
(excellence).
Specialization is for insects. (Heinlein) - Have Pun, Will Babble!
(Aronson)

On Fri, Dec 16, 2011 at 10:22 AM, Dave A. <
[email protected]> wrote:

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

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

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.

On Fri, Dec 16, 2011 at 10:36, Javier Q. [email protected]
wrote:

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.

-Dave


LOOKING FOR WORK! What: Ruby (on/off Rails), Python, other modern
languages.
Where: Northern Virginia, Washington DC (near Orange Line), and remote
work.
See: davearonson.com (main) * codosaur.us (code) * dare2xl.com
(excellence).
Specialization is for insects. (Heinlein) - Have Pun, Will Babble!
(Aronson)