Almost solved the problem myself. Since the Message model in my body field is encrypted in AES I rewrote the method to_param body - a cipher text like wuTekBX7p0K+olP6Vd/8Jw==$okRXvvSB1ZRRuhxF3O9EIg== .

 def to_param "#{id}-#{body.tr('^A-Za-z0-9', '')[0..12].insert(3, self.id.to_s.chars.each_slice(2).map(&:join).first).insert(9, self.id.to_s.chars.each_slice(2).map(&:join).last).parameterize}" end 

Yes, it looks a bit strange :)

In the end, the link is obtained /messages/2-wut2ekbx72p0kol But you need to do without the id in the beginning and so that it is unique.

  • one
    It seems to me that the best way to use the database tool for this is to create a link table between identifiers and links, and generate links using the GUID when inserting a new id into the table. - Alex Chermenin
  • @Alex Chermenin c GUID is not a bad option, some characters will be a bit too much (I would be up to 16), but it can still work. So you need to create a table of correspondence GUID code - id. And then through it to get the object. Difficult, but as an option fit. - Escobar
  • @Alex Chermenin how to react to inserting a new object with id into the messages table? Tried via after_save / after_create does not work, message does not yet have an id at that time. - Escobar

1 answer 1

Before creating a record in the messages table, generate the necessary code, write it in a separate field in the table, for example, link_id. On it you will just check the uniqueness. Naturally, it needs an index.

  before_create :generate_link_id def generate_link_id self.link_id = SecureRandom.hex(10) self.link_id = SecureRandom.hex(10) while Message.find_by_link_id(self.link_id) end 

route will be accordingly

 get "/message/:link_id" => "messages#show" 

According to it you will look for a message in the controller.

 def show @message = Message.find_by_link_id! params[:link_id] end 

Trying to portray something from an encrypted body is a so-called idea. In theory, you can, of course, come up with some unique hash function, but why?