1

I am working on a Rails application where users can add posts without registration. I want to generate a random, unique key and provide a link to edit their post, for example: http://mygreatapp.com/post/edit/f7smSDf34Sad . Similar approach is used by Craigslist.

My idea was to generate a random, unique string on post creation and save it in the database, together with other post data. Then check if the string in the databases matches the one in the request. Is the solution safe?

How would you implement it?

EDIT: Thanks for responses. However, generating random strings is not an issue. Safety and implementation in the database is my concern.

Jacek
  • 1,874
  • 5
  • 21
  • 32
  • Make sure the key is not guessable and not shown on any public page. Furthermore you could send out a notification to the post's owner after the post was edited. – Stefan May 31 '12 at 15:37

2 Answers2

1

If I were going to implement this I would use the friendly_id gem since what you're basically doing is creating a unique slug for each record in your DB. friendly_id by default will use a column to create the slug. You could tell friendly_id to use the id column and then override their normalize_friendly_id method.

In that method you would generate a unique string and then return it. The text that is returned by this method is what friendly_id will use to generate your slug.

To generate the slug you could simply use an MD5 hash or you could do something like this:

(0...50).map{ ('a'..'z').to_a[rand(26)] }.join

The benefit to using this approach instead of simply creating/storing the slug yourself is that you won't have to do Post::find_by_slug(slug), you can still use Post::find(slug) because friendly_id handles looking up the record by the slug.

There is a Railscasts episode that covers the friendly_id gem

Community
  • 1
  • 1
Kyle Decot
  • 19,418
  • 35
  • 132
  • 245
0

I use something like that in my app (to_param is called by your controllers/views to generate routes)

class Post < AR::Base
  def to_param
    Digest::SHA1.hexdigest("--#{self.if}--#{self.created_at}--")
  end
end

The only problem is that SHA1 generate long strings. You can use MD5 instead...

sailor
  • 7,218
  • 3
  • 22
  • 33