Topic: This belongs in the model, not having an easy time getting it there

I have a user model that I'd like to generate a invitation token with. The use case would be after the user signs up, they can invite others to the application through their personalized url. Something like: www.ourgreatnewapp.com/invitation-to-join-from/@user.invitation token.

I've been working for a while on simply generating a unique token but couldn't keep from generating an inifinte loop in the model. I was hoping someone could help me here. I'm sure it's simple code, I'm just missing something.

Here's what I have now:

#controller
@user = User.new(params[:user])
@user.make_new_token

#model
def make_new_token
      fn = full_name.gsub(/\s/, "")
      self.invite_token = fn
      
      valid? #need to run validations on this model to see if there's an error with the invite token
      while errors.on(:invite_token)
        puts self.invite_token = fn + "#{i ||= 1}"
        i+=1
        valid? #important! to avoid infinite loop need to re-check if errors
      end
      self.invite_token
  end

I really think this belongs in the model to be executed before the validations but I haven't been able to make it work. Thanks in advance for your help.

Ruby on Rails application developer - www.brycemcdonnell.com

Re: This belongs in the model, not having an easy time getting it there

Why not just generate a hash based on the time and some user element?

Digest::SHA1.hexdigest("#{full_name}-#{Time.now}")

Or something of the sort.

Re: This belongs in the model, not having an easy time getting it there

there's also the UUID gem which gives you a TRULY unique (and massive!) identifier, guaranteed to never be the same (it takes mac address into account!).  That might be overkill for you though - freezzo's suggestion seems sufficient.

Last edited by Max Williams (2009-10-07 11:07:03)

###########################################
#If i've helped you then please recommend me at Working With Rails:
#http://www.workingwithrails.com/person/ … i-williams

Re: This belongs in the model, not having an easy time getting it there

thanks guys. The structure of the invite token has been decreed by the client. I'm not at liberty to make changes to that. What's really got me bugged is why I can't run the validation (and thus iterate the invite token if necessary) in the model just before the validations run.

Ruby on Rails application developer - www.brycemcdonnell.com

Re: This belongs in the model, not having an easy time getting it there

brycebrycebaby wrote:

thanks guys. The structure of the invite token has been decreed by the client. I'm not at liberty to make changes to that. What's really got me bugged is why I can't run the validation (and thus iterate the invite token if necessary) in the model just before the validations run.

you could use a before validation callback
http://www.railsbrain.com/api/rails-2.2 … validation

This could get messy since you're calling valid? inside the method - you'd get into an infinite loop i think.

What is the logic you use to determine if the invite_token is valid or not?  I would use that logic inside the method, which sets it, rather than calling 'valid?', and then you can call it with before_validate, like

before_validation_on_create :make_new_token

Last edited by Max Williams (2009-10-07 11:16:31)

###########################################
#If i've helped you then please recommend me at Working With Rails:
#http://www.workingwithrails.com/person/ … i-williams

Re: This belongs in the model, not having an easy time getting it there

Infinite loops are my forte smile

The validation I'm calling on :invite_token is validates_uniqueness_of :invite_token ...

Interestingly I have tried the before_validation_on_create and that's where I'm at now. I was trying to go as easy on the db as possible.

At one time I had:

until User.find_by_invite_token(self.invite_token).blank?
  #iterate integers
end

It just pounds the database and I thought validates_uniqueness had taken a different approach. As I look at the source it looks like it's basically the same thing. Does that look right or is there a better, more database friendly, way to do that?

Thanks again,
Bryce

Ruby on Rails application developer - www.brycemcdonnell.com

Re: This belongs in the model, not having an easy time getting it there

Well, you could load them all out of the database in one go, get a unique one, and then write the user's details into the db in a transaction, that should be safe.  I guess you'd want to do this in an after_create callback and then change the validation to only be validate_on_update instead of the normal validate, which is update and create.

###########################################
#If i've helped you then please recommend me at Working With Rails:
#http://www.workingwithrails.com/person/ … i-williams

Re: This belongs in the model, not having an easy time getting it there

Thanks for weighing in. I thought there might have been a better solution, but I have some room to run now.

Thanks,
Bryce

Ruby on Rails application developer - www.brycemcdonnell.com