0

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?

  • if its non-null in DB I cannot do it after_save
  • I have tried update_attribute rather than direct attribute - this won't work as new object

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 

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.