# Implementation ideas for a unique identifier

**URL:** <https://www.ruby-forum.com/t/implementation-ideas-for-a-unique-identifier/119413>\
**Category:** Rails\
**Created:** [November 6, 2007, 8:26pm UTC](https://www.ruby-forum.com/t/implementation-ideas-for-a-unique-identifier/119413 "2007-11-06T20:26:20Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jmaziarz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e0b2c6/32.png) [@jmaziarz](https://www.ruby-forum.com/u/jmaziarz)\
**Post date:** [November 6, 2007, 8:26pm UTC](https://www.ruby-forum.com/t/implementation-ideas-for-a-unique-identifier/119413/1 "2007-11-06T20:26:20Z")

</div>

I have an Item model that uses acts\_as\_nested\_set (via  
better\_nested\_set plugin) to maintain tree structures of Items. There  
can potentially be thousands of “root” Items. A requirement is that  
each “root” Item have a unique identifier in the form ‘YYMMDD-nnnnnn’  
where nnnnnn is a sequential counter (e.g. 071106-000024). There can  
be no gaps in this sequential counter.

For example, a “root” Item with 57 children is added to the database.  
The “root” has a unique identifier of ‘071106-000001’ because it is  
the first “root” item (Item#id = 1). The next “root” item (Item#id =  
58) must have a unique identifier of ‘071106-000002’ and NOT  
‘071106-000058’.

How would you implement this “sequential counter”?

---

<div class="post-metadata">

**Author:** ![jmaziarz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e0b2c6/32.png) [@jmaziarz](https://www.ruby-forum.com/u/jmaziarz)\
**Post date:** [November 6, 2007, 9:30pm UTC](https://www.ruby-forum.com/t/implementation-ideas-for-a-unique-identifier/119413/2 "2007-11-06T21:30:12Z")

</div>

On Nov 6, 2007, at 8:25 PM, removed\_email\_address@domain.invalid wrote:

> 1. must have a unique identifier of ‘071106-000002’ and NOT  
> ‘071106-000058’.

The rows have their own regular integer keys, and that’s an additional  
column that is NULL for non-root nodes?

– fxn

---

<div class="post-metadata">

**Author:** ![jmaziarz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e0b2c6/32.png) [@jmaziarz](https://www.ruby-forum.com/u/jmaziarz)\
**Post date:** [November 6, 2007, 9:30pm UTC](https://www.ruby-forum.com/t/implementation-ideas-for-a-unique-identifier/119413/3 "2007-11-06T21:30:47Z")

</div>

> 1. must have a unique identifier of ‘071106-000002’ and NOT  
> ‘071106-000058’.
> 
> How would you implement this “sequential counter”?

Have a table with two columns. The first is the date. The second is an  
integer.

Write a routine that gets you the next highest value for the given date  
and then updates the table with that new value for next time. And put a  
gigantic lock around the entire thing so that you don’t have any race  
conditions.

If it were me, I’d spend some time trying to remove that restriction,  
but  
I’m guessing you’re stuck with it.

What happens in this situation:

- Lock.

- Get the next NNNN value.

- Update the database for next time.

- Unlock.

- Try and use it, but it freaks out, entire Rails app crashes.

- Restart app.

At this point you have a hole in your sequence… how do you even know  
if  
you have a hole? What do you do?

---

<div class="post-metadata">

**Author:** ![jmaziarz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e0b2c6/32.png) [@jmaziarz](https://www.ruby-forum.com/u/jmaziarz)\
**Post date:** [November 6, 2007, 9:53pm UTC](https://www.ruby-forum.com/t/implementation-ideas-for-a-unique-identifier/119413/4 "2007-11-06T21:53:36Z")

</div>

Sometimes writing it out in the form of a question gets the creative  
juices flowing.What if I added an attribute to the items table named  
“sequence”. Then I could use an after\_create callback and two private  
methods such as:

def after\_create  
if self.root?  
update\_attribute(:sequence, generate\_sequence)  
update\_attribute(:identifier, generate\_identifier)  
end  
end

private

def generate\_sequence  
Item.maximum(:sequence, :conditions =\> [‘parent\_id != ?’, ‘NULL’])

- 1  
end

---

<div class="post-metadata">

**Author:** ![jmaziarz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e0b2c6/32.png) [@jmaziarz](https://www.ruby-forum.com/u/jmaziarz)\
**Post date:** [November 6, 2007, 9:45pm UTC](https://www.ruby-forum.com/t/implementation-ideas-for-a-unique-identifier/119413/5 "2007-11-06T21:45:59Z")

</div>

Correct.

---

<div class="post-metadata">

**Author:** ![jmaziarz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e0b2c6/32.png) [@jmaziarz](https://www.ruby-forum.com/u/jmaziarz)\
**Post date:** [November 6, 2007, 11:26pm UTC](https://www.ruby-forum.com/t/implementation-ideas-for-a-unique-identifier/119413/6 "2007-11-06T23:26:15Z")

</div>

Here is my working solution:

class AddSequenceToItems \< ActiveRecord::Migration  
def self.up  
add\_column :items, :sequence, :integer  
end

def self.down  
remove\_column :items, :sequence  
end  
end

class Item \< ActiveRecord::Base  
def after\_create  
# This item doesn’t already have a root, so this is a new root  
item  
update\_attribute(:root\_id, self.id) if self.root\_id.nil?

```
if root?
  update_attribute(:sequence, generate_sequence)
  update_attribute(:identifier, generate_identifier)
end

```

end

def sequence(padded = false)  
padded ? padded\_sequence : self[:sequence]  
end

private

def self.maximum\_sequence  
Item.maximum(:sequence) || 0  
end

def generate\_sequence  
self.class.maximum\_sequence + 1  
end

def generate\_identifier  
“#{self.created\_on.strftime(’%y%m%d’)}-#{padded\_sequence}”  
end

def padded\_sequence(length = 6, str = ‘0’)  
self[:sequence].to\_s.rjust(length, str)  
end  
end
