Mateusz
Mateusz

Reputation: 1197

hash instead of id

I want to use auto-generated hash'es instead of auto-incremented integers in my activerecords as primary keys. This raises two questions:

  1. how to perform this generation in most efficient way?
  2. how to handle possibility that generated hash exists already in table?

Regards, Mateusz

Upvotes: 9

Views: 8364

Answers (4)

Mika
Mika

Reputation: 1479

If you want this because you don't want to show the id in the web url. You can use a gem like https://github.com/peterhellberg/hashids.rb

It creates a reversible hash from your database id so the hash does not need to be stored in the database.

Use it in your models to_param method.

class MyModel < ActiveRecord::Base

  def to_param
    Hashids.new("salt").encode(id)
  end
end

And decode the hash before finding the record from the database.

def show
  id = Hashids.new("salt").decode(params[:id]).try(:first)
  record = MyModel.find(id)
end

Upvotes: 9

Hilde
Hilde

Reputation: 456

It might not be exactly what you asked for. But I had a similar problem where I wanted to use a hash instead of the ID in the URL. My solution follows

  1. I added a column in my table called privatelink
  2. In my model i wrote:
  #changes the url to use privatelink instead of the id
  def to_param
    privatelink
  end

  #calls the private method set_privatelink
  before_create :set_privatelink

  private

  #generates a unique hash looking something like this: c24bea1693d9e56a1878cb83f252fba05532d9d0
  def set_privatelink
    self.privatelink = Digest::SHA1.hexdigest([Time.now, rand].join)
  end

Source: Railcast #63 Model Name in URL - shows how to use the to_param method

Upvotes: 4

nathanvda
nathanvda

Reputation: 50057

When using Oracle i had the case where I wanted to create the ID ourselves (and not use a sequence), and in this post i provide the details how i did that. In short the code:

# a small patch as proposed by the author of OracleEnhancedAdapter: http://blog.rayapps.com/2008/05/13/activerecord-oracle-enhanced-adapter/#comment-240
# if a ActiveRecord model has a sequence with name "autogenerated", the id will not be filled in from any sequence
ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
  alias_method :orig_next_sequence_value, :next_sequence_value

  def next_sequence_value(sequence_name)
    if sequence_name == 'autogenerated'
      # we assume id must have gotten a good value before insert!
      id
    else
      orig_next_sequence_value(sequence_name)
    end
  end
end

while this solution is specific to Oracle-enhanced, i am assuming inside the other adapters you can overrule the same method (next_sequence_value).

Upvotes: 0

Spyros
Spyros

Reputation: 48626

It's not a duplicate of your question, but i think you want to do the same thing :

Assigning Each User a Unique 100 character Hash in Ruby on Rails

Upvotes: 2

Related Questions