Module: ApiKeys::FormBuilderExtensions

Defined in:
lib/api_keys/form_builder_extensions.rb

Overview

Opt-in form builder extensions for API key forms.

These helpers reduce boilerplate while letting you control the styling. Include them in your form builder to use:

# In config/initializers/api_keys.rb:
Rails.application.config.to_prepare do
ActionView::Helpers::FormBuilder.include(ApiKeys::FormBuilderExtensions)
end

Examples:

Expiration select

<%= form.api_key_expiration_select(class: "my-select-class") %>

Scopes checkboxes with block for custom rendering

<%= form.api_key_scopes_checkboxes(@scopes) do |scope, checked| %>
  <label>
    <%= check_box_tag "api_key[scopes][]", scope, checked, class: "my-checkbox" %>
    <%= scope %>
  </label>
<% end %>

Instance Method Summary collapse

Instance Method Details

#api_key_expiration_select(options = {}, html_options = {}) ⇒ String

Renders a select field for API key expiration presets.

Examples:

Basic usage

<%= form.api_key_expiration_select %>

With Tailwind classes

<%= form.api_key_expiration_select(class: "w-full px-4 py-3 border rounded-lg") %>

With custom default

<%= form.api_key_expiration_select(selected: "30_days") %>

Parameters:

  • options (Hash) (defaults to: {})

    Options passed to the select helper

  • html_options (Hash) (defaults to: {})

    HTML attributes for the select element

Returns:

  • (String)

    HTML select element



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/api_keys/form_builder_extensions.rb', line 41

def api_key_expiration_select(options = {}, html_options = {})
  # expires_at_preset is a form-only param, not a model attribute
  # So we only use the provided :selected option or default
  selected = options.delete(:selected) || ApiKeys::ExpirationOptions.default_value

  select(
    :expires_at_preset,
    @template.options_for_select(ApiKeys::ExpirationOptions.for_select, selected),
    options,
    html_options
  )
end

#api_key_scopes_checkboxes(scopes, checked: nil, &block) ⇒ String, Array

Renders checkboxes for API key scopes.

If a block is given, yields each scope and its checked state for custom rendering. If no block is given, returns an array of checkbox data for manual iteration.

Examples:

With block (recommended for custom styling)

<%= form.api_key_scopes_checkboxes(@scopes) do |scope, checked| %>
  <label class="flex items-center gap-2">
    <%= check_box_tag "api_key[scopes][]", scope, checked, class: "rounded" %>
    <code><%= scope %></code>
  </label>
<% end %>

Simple rendering without block

<% form.api_key_scopes_checkboxes(@scopes).each do |scope_data| %>
  <%= check_box_tag "api_key[scopes][]", scope_data[:value], scope_data[:checked] %>
  <%= scope_data[:value] %>
<% end %>

Parameters:

  • scopes (Array<String>)

    Available scopes to render

  • checked (Symbol, Array) (defaults to: nil)

    Which scopes should be checked:

    • :all (default for new records) - all scopes checked
    • :none - no scopes checked
    • Array - specific scopes to check
    • nil - uses the object's current scopes

Returns:

  • (String, Array)

    HTML if block given, otherwise array of scope data



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/api_keys/form_builder_extensions.rb', line 81

def api_key_scopes_checkboxes(scopes, checked: nil, &block)
  # Determine which scopes should be checked
  checked_scopes = resolve_checked_scopes(scopes, checked)

  scope_data = scopes.map do |scope|
    {
      value: scope,
      checked: checked_scopes.include?(scope),
      field_name: "#{object_name}[scopes][]"
    }
  end

  if block_given?
    # Yield each scope for custom rendering
    safe_buffer = ActiveSupport::SafeBuffer.new
    scope_data.each do |data|
      safe_buffer << @template.capture { yield(data[:value], data[:checked]) }
    end
    safe_buffer
  else
    # Return raw data for manual iteration
    scope_data
  end
end

#api_key_token_dataHash

Returns structured data for building a token display UI. Useful when you need to build a custom token display with copy functionality.

Examples:

<% data = form.api_key_token_data %>
<code><%= data[:masked] %></code>
<% if data[:viewable] %>
  <button data-token="<%= data[:full] %>">Copy</button>
<% end %>

Returns:

  • (Hash)

    Token display data with keys:

    • :masked [String] The masked token (e.g., "sk_live_••••abc")
    • :full [String, nil] The full token (only for viewable public keys)
    • :viewable [Boolean] Whether the full token can be displayed
    • :type [Symbol] The key type (:publishable, :secret, or nil)
    • :environment [String, nil] The environment (e.g., "live", "test")


123
124
125
126
127
128
129
130
131
132
133
# File 'lib/api_keys/form_builder_extensions.rb', line 123

def api_key_token_data
  return {} unless object.respond_to?(:masked_token)

  {
    masked: object.masked_token,
    full: object.viewable_token,
    viewable: object.respond_to?(:public_key_type?) && object.public_key_type?,
    type: object.key_type&.to_sym,
    environment: object.environment
  }
end