Validates_uniqueness_of with a condition


#1

Hi,
I need to check the uniqueness of an attribute (a doc number) using a
condition (a specific year), I’ve found validates_uniqueness_of
:number, but I need to tell it I just want to check a specific year.
I’ve found :scope but I haven’t really understood it’s meaning, Can I
scope on a specific year?
Thanks,
Enrico


“The only thing necessary for the triumph of evil
is for good men to do nothing”
Edmund Burke


#2

Hi Enrico,

What do you mean you want to have it unique to a given year? I that
with
some other criteria as well?


#3

Hi Enrico,

Enrico T. wrote:

I need to check the uniqueness of an attribute (a doc number) using a
condition (a specific year), I’ve found validates_uniqueness_of
:number, but I need to tell it I just want to check a specific year. I’ve
found :scope but I haven’t really understood it’s meaning, Can I
scope on a specific year?

The scope parameter allows you to verify uniqueness within a subset of
the
records in a table. If we assume a table definition as follows…

create table docs;
id int not null auto_increment,
doc_num int,
year date,
primary key (id)
);

then including

validates_uniqueness_of :doc_num, :scope => “year”

in your doc model will allow you to enter:

doc_num = ‘1’ year = ‘2000’
doc_num = ‘2’ year = ‘2000’
doc_num = ‘1’ year = ‘2001’
doc_num = ‘2’ year = ‘2001’
etc.

but will not allow any duplicates of these entries.

hth,
Bill


#4

the target is to check on document update, not to choose an already
used number. Numbers restart from 1 at the end of the year… so I
also need to specify an year.
First of all I need to know if the number is beeing changed. Then I’ll
check if the new number isn’t already used in the current year.
Right now I’ve used this way:
def validate_on_update
exist = Document.find(:first, :conditions => “type =
‘#{self.type}’ AND extract(year from created_at) = #{Time.now.year}
AND number = #{self.number} AND id != #{self.id}”)
if exist
errors.add_to_base(“I can’t update the doc with this number!”)
end
end
this is kinda uggly cz I always query the DB,
I guess I could control with a before_filter (of before something I
forgot) if the new value is different than the old one. Then query the
DB.
Anyway…

in your doc model will allow you to enter:

doc_num = ‘1’ year = ‘2000’
doc_num = ‘2’ year = ‘2000’
doc_num = ‘1’ year = ‘2001’
doc_num = ‘2’ year = ‘2001’
etc.

but will not allow any duplicates of these entries.
so my guess was right, the point is I don’t have a column year, I have
a created_at datetime column. Can I estrapolate the year and put it in
the scope?
I’ve tried putting the psql extract(year from created_at) within
scope but it didn’t worked…
maybe I’ll try to create a “fake” method called year based on the
record datestamp…


“The only thing necessary for the triumph of evil
is for good men to do nothing”
Edmund Burke


#5

Enrico T. wrote:

the target is to check on document update, not to choose an already used
number. Numbers restart from 1 at the end of the year… so I
also need to specify an year.

so my guess was right, the point is I don’t have a column year, I have a
created_at datetime column. Can I estrapolate the year and put it in the
scope?

Yes, you will need a column for just the year and yes, you can extract
that
from the created_at column if you want / need to. If you’re dealing
with an
existing database, I’d probably do the extraction as part of a
migration.
After the initial migration, I’d put the code to populate the year
column in
the controller rather than muddying up the model, but I imagine either
will
work. Once you have a table with the year column populated for all the
records in it, the 'validates_uniqueness_of :doc_num, :scope => “year” ’
validation will do what you’re looking for.

Best regards,
Bill