Validates_uniqueness_of with a condition

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

Hi Enrico,

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

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

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

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