Nick
Nick

Reputation: 3090

Before_create isn't working

In my Article model file I have:

before_create   :generate_token
validates :token, presence: true
private
def generate_token
  self.token = SecureRandom.urlsafe_base64
end

And in my migration:

t.string :token, null: false

But now tests that create an article fail with ActiveRecord::RecordInvalid: Validation failed: Token can't be blank. In these tests I indeed don't give a value for token. However, shouldn't the before_create method above do this automatically? It concerns test that call upon the create method for a new author, of which the controller method includes the line @author.articles.create! (so without a token value for the article).

P.S. I put the debugger at the top of the generate_token method, and it never fires for any of the tests.

Upvotes: 3

Views: 1152

Answers (3)

Richard Peck
Richard Peck

Reputation: 76774

#app/models/article.rb
class Article < ActiveRecord::Base
   before_validation :generate_token, on: :create
   validates :token, presence: true

   private

   def generate_token
        self.token = loop do
            random_token = SecureRandom.urlsafe_base64
            break random_token unless self.class.exists? random_token
        end
   end
end

A much better way is to use has_secure_token (included in Rails 5; gem here):

#Gemfile
gem "has_secure_token" #-> not needed for Rails 5

#app/models/article.rb
class Article < ActiveRecord::Base
   has_secure_token
end

Upvotes: 4

Chris Cherry
Chris Cherry

Reputation: 28554

You probably want to use

before_validation :generate_token, on: :create

That will fire at exactly the time you are wanting it to and only on the initial creation, not on every save.

Upvotes: 2

yzalavin
yzalavin

Reputation: 1836

Try to change before_create to before_validation.

Upvotes: 0

Related Questions