Friday, January 4, 2019

postgresql - Generating an Instagram- or Youtube-like unguessable string ID in ruby/ActiveRecord



Upon creating an instance of a given ActiveRecord model object, I need to generate a shortish (6-8 characters) unique string to use as an identifier in URLs, in the style of Instagram's photo URLs (like http://instagram.com/p/P541i4ErdL/, which I just scrambled to be a 404) or Youtube's video URLs (like http://www.youtube.com/watch?v=oHg5SJYRHA0).



What's the best way to go about doing this? Is it easiest to just create a random string repeatedly until it's unique? Is there a way to hash/shuffle the integer id in such a way that users can't hack the URL by changing one character (like I did with the 404'd Instagram link above) and end up at a new record?



Answer



You could do something like this:



random_attribute.rb



module RandomAttribute

def generate_unique_random_base64(attribute, n)
until random_is_unique?(attribute)
self.send(:"#{attribute}=", random_base64(n))

end
end

def generate_unique_random_hex(attribute, n)
until random_is_unique?(attribute)
self.send(:"#{attribute}=", SecureRandom.hex(n/2))
end
end

private


def random_is_unique?(attribute)
val = self.send(:"#{attribute}")
val && !self.class.send(:"find_by_#{attribute}", val)
end

def random_base64(n)
val = base64_url
val += base64_url while val.length < n
val.slice(0..(n-1))

end

def base64_url
SecureRandom.base64(60).downcase.gsub(/\W/, '')
end
end
Raw


user.rb




class Post < ActiveRecord::Base

include RandomAttribute
before_validation :generate_key, on: :create

private

def generate_key
generate_unique_random_hex(:key, 32)

end
end

No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...