Reputation: 2224
I have a method that creates a token. This worked and now I want to also ensure uniqueness of the token. Therefore I added while self.class.exists?(api_digest: api_digest)
(see below). However, now all sorts of test fail with the error:
ArgumentError: wrong number of arguments (0 for 2)
referring to def remember_api(type, user)
which is in a sessions helper. Any ideas what I'm doing wrong?
User model:
def remember_api
self.api_token = User.new_token # Creates new api_token.
update_attributes(api_digest: User.digest(api_token), api_sent_at: Time.zone.now)
end while self.class.exists?(api_digest: api_digest)
def User.new_token
SecureRandom.urlsafe_base64
end
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
Sessions helper:
def remember_api(type, user)
if type == "user"
user.remember_api
end
end
Update: So I tried the method below. But that doesn't seem to work either as it gets into an infinite loop.
def remember_api
begin
self.api_token = User.new_token
update_attributes(api_digest: User.digest(api_token), api_sent_at: Time.zone.now)
end while self.class.exists?(api_digest: api_digest)
end
Update2: I've got model validation for uniqueness on api_digest
and tried the following:
def remember_api
begin
self.api_token = User.new_token
api_digest = User.digest(api_token)
debugger
end until update_attributes(api_digest: api_digest, api_sent_at: Time.zone.now)
end
This goes wrong, again creating an infinite loop. It proofs that once I move update_attributes
behind the end
, debugger shows that api_digest
and api_token
are nil
. And self
returns: User(id: integer, email: string, username: string, fullname: string, ...
. If I place update_attributes
inside the begin...end
(below debugger), they are not nil
and self
returns: <Userid: 1001, email: "[email protected]", username: "mystring1", ...
.
Upvotes: 1
Views: 640
Reputation: 872
The second api_digest
should be self.api_digest
. It is because it is looking for a local variable called api_digest, but you meant an attribute on this model
Like this:
def remember_api
begin
self.api_token = User.new_token
update_attributes(api_digest: User.digest(api_token), api_sent_at: Time.zone.now)
end while self.class.exists?(api_digest: self.api_digest)
end
Update
When you call update_attributes
, it will return true if it updates and passes validation. Then it'll go ahead and check if it exists and it does because you just updated it in there, so it'll loop again and lead to infinite loop
If update_attributes
returns false, that means it exists and meet the while statement and loop. This is the only time it does what you expected.
begin
self.api_token = User.new_token
self.api_digest = User.digest(api_token)
end while self.class.exists?(api_digest: self.api_digest)
self.api_sent_at = Time.zone.now
self.save!
Doc: update
Upvotes: 2