A developer notebook I should have started 10 years ago..

Simple token authentication for an API Rails application

How can I quickly set up a token authentication for my Rails API app?

module API
  class V1Controller < ApplicationController
    before_action :authenticate_user_with_token

    private 
    
    def authenticate_user_with_token
      authenticate_with_http_token do |token, _|
        @api_user ||= User.find_by(token: token)
      end
      return if @api_user

      render json: { message: "Bad credentials" }, status: :unauthorized
    end
  end
end

And now, inherit all your controllers from API::V1Controller.
Rails is expecting the token through the request headers as, "Authorization" => "Token <<token>>".

If your base controller inherits from ActionController::API, you must include the ` ActionController::HttpAuthentication::Token::ControllerMethods` module.

module API
  class V2Controller < ActionController::API
    include ActionController::HttpAuthentication::Token::ControllerMethods

    ...
  end
end

Resources:

  • https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic.html
  • https://apidock.com/rails/v6.1.3.1/ActionController/HttpAuthentication/Token/ControllerMethods

FactoryBot traits for model association

TLDR

How can I specify traits for model associations in factory_bot?

FactoryBot.define do
  factory :user do
    # `public_company` is the model reference name
    # `company` is the association factory name
    # `public` is the trait name
    association :public_company, factory: %i[company public]
  end
end

FactoryBot traits

Let’s define User.

class User < ApplicationRecord
  belongs_to :company
end

Easy peasy for the related factory.

FactoryBot.define do
  factory :user do
    association :company # explicit association
  end
end

# or

FactoryBot.define do
  factory :user do
    company # implicit association
  end
end

Now, we’re updating the class name of the relation.

class User < ApplicationRecord
  belongs_to :public_company, class_name: "Company"
end

In the factory, we must set the factory param.

FactoryBot.define do
  factory :user do
    association :public_company, factory: :company
  end
end

And finally, if we need to specify the trait of the used factory.

FactoryBot.define do
  factory :company do
    trait :public do
      public { true }
    end
  end
end

We must set the factory param with an array of [:factory_name, :trait_name].

FactoryBot.define do
  factory :user do
    association :public_company, factory: %i[company public]
  end
end

Resources: