heartcombo/simple_form · error · ArgumentError

Association cannot be used in forms not associated with an o

Error message

Association cannot be used in forms not associated with an object

What it means

f.association needs the form's @object to read the ActiveRecord reflection, infer the attribute name (e.g. category_id) and fetch the collection. If the builder has no object — as with simple_form_for :search — and no block is given, it raises ArgumentError (lib/simple_form/form_builder.rb:213). With a block it delegates to simple_fields_for instead and never raises.

Source

Thrown at lib/simple_form/form_builder.rb:213

    # When a block is given, association simple behaves as a proxy to
    # simple_fields_for:
    #
    #   f.association :company do |c|
    #     c.input :name
    #     c.input :type
    #   end
    #
    # From the options above, only :collection can also be supplied.
    #
    # Please note that the association helper is currently only tested with Active Record. Depending on the ORM you are using your mileage may vary.
    #
    def association(association, options = {}, &block)
      options = options.dup

      return simple_fields_for(*[association,
        options.delete(:collection), options].compact, &block) if block_given?

      raise ArgumentError, "Association cannot be used in forms not associated with an object" unless @object

      reflection = find_association_reflection(association)
      raise "Association #{association.inspect} not found" unless reflection

      options[:as] ||= :select
      options[:collection] ||= fetch_association_collection(reflection, options)

      attribute = build_association_attribute(reflection, association, options)

      input(attribute, options.merge(reflection: reflection))
    end

    # Creates a button:
    #
    #   form_for @user do |f|
    #     f.button :submit
    #   end
    #

View on GitHub (pinned to 18f38aad0b)

Solutions

  1. For object-less forms, replace association with an explicit collection input: f.input :category_id, collection: Category.order(:name)
  2. Back the form with a real object — a persisted or unsaved record, form object or presenter — so the reflection can be read
  3. If you want nested fields, pass a block: f.association :category do |c| ... end, which delegates to simple_fields_for and bypasses the check

Example fix

# before
<%= simple_form_for :search, method: :get do |f| %>
  <%= f.association :category %>  <!-- ArgumentError: not associated with an object -->
<% end %>

# after
<%= simple_form_for :search, method: :get do |f| %>
  <%= f.input :category_id, collection: Category.order(:name), label_method: :name, value_method: :id %>
<% end %>
Defensive patterns

Strategy: validation

Validate before calling

if f.object.present?
  f.association :category
else
  f.input :category_id, collection: Category.order(:name)
end

Prevention

When it happens

Trigger: simple_form_for :search, method: :get do |f| f.association :category end (symbol form, object is nil); simple_form_for(@search) where @search is nil because the controller never assigned it; any builder whose object is nil calling association without a block.

Common situations: Search/filter forms that only need a dropdown of records; shared form partials reused for both model-backed and object-less forms; controller refactor that stops setting the instance variable the view builds its form from.

Related errors


AI-assisted analysis of heartcombo/simple_form@18f38aad0b (2026-08-21). Data as JSON: /api/errors/7c4c0fd55acfc4ef. Report an issue: GitHub.