Reputation: 1342
trying to create an api_key for my user. have setup so its non-null.
rails 4, not -null is triggered, but i am creating the access_token
item before create
so why?
if i puts
in def generate_access_token
I can see access_token is populated
its almost like it doesn't include access token (see db record at bottom) as part of the save command.
stumped! i must have missed something silly, surely?
after_save
test .log
SQL (0.5ms) INSERT INTO "api_keys" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2016-12-21 08:09:07.304051"], ["updated_at", "2016-12-21 08:09:07.304051"]]
* missing the access_token * why?
error
$ rspec spec/models/api_key_spec.rb
F
Failures:
1) ApiKey populates token
Failure/Error: let!(:a) { FactoryGirl.create(:api_key) }
ActiveRecord::StatementInvalid:
SQLite3::ConstraintException: NOT NULL constraint failed: api_keys.user_id: INSERT INTO "api_keys" ("created_at", "updated_at") VALUES (?, ?)
.....
# --- Caused by: ---
# SQLite3::ConstraintException:
# NOT NULL constraint failed: api_keys.user_id
# /Users/ben.forrest/.rvm/gems/ruby-2.2.5@baseapi/gems/sqlite3-1.3.12/lib/sqlite3/statement.rb:108:in `step'
Finished in 0.11903 seconds (files took 3.32 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/models/api_key_spec.rb:5 # ApiKey populates token
api_key_spec.rb
require 'rails_helper'
RSpec.describe ApiKey, type: :model do
let!(:a) { FactoryGirl.create(:api_key) }
it "populates token" do
expect(a.access_token).to match /[A-Za-z0-9]{32}/
end
end
api_key.rb
class ApiKey < ActiveRecord::Base
attr_accessor :access_token, :expires_at, :user_id, :active, :application
before_create :generate_access_token
before_create :set_expiration
belongs_to :user
def expired?
DateTime.now >= self.expires_at
end
private
def generate_access_token
begin
self.access_token = SecureRandom.hex
end while self.class.exists?(access_token: access_token)
puts "**** access_token: #{access_token}****" # this shows it is created
end
def set_expiration
self.expires_at = DateTime.now+30
end
end
migration
class CreateApiKeys < ActiveRecord::Migration
def change
create_table :api_keys do |t|
t.string :access_token, null: false
t.integer :user_id, null: false
t.boolean :active, null: false, default: true
t.datetime :expires_at
t.timestamps
end
add_index :api_keys, ["user_id"], name: "index_api_keys_on_user_id", unique: false
add_index :api_keys, ["access_token"], name: "index_api_keys_on_access_token", unique: true
end
end
Upvotes: 0
Views: 224
Reputation: 23859
while self.class.exists?(access_token: access_token)
becomes false for access_token = nil
. Try assigning the token first, before the begin
.
def generate_access_token
return if access_token
token = SecureRandom.hex
token = SecureRandom.hex while self.class.exists?(access_token: access_token)
self.access_token = token
end
Upvotes: 1