Tay James
Tay James

Reputation: 31

ActiveAdmin nested has_many

Consider the following models:

class User < ApplicationRecord
    accepts_nested_attributes_for :memberships, allow_destroy: true

    has_many :memberships, dependent: :destroy
    has_many :accounts, through: :memberships
end

class Account < ApplicationRecord
  accepts_nested_attributes_for :memberships, allow_destroy: true
  accepts_nested_attributes_for :users, allow_destroy: true

  has_many :memberships, dependent: :destroy
  has_many :users, through: :memberships
end

class Membership < ApplicationRecord
  belongs_to :account
  belongs_to :user
  
  before_validation { self.role = "admin" if role.blank? }

  validates :role, presence: true

  pg_enum :role, %i[admin support user]
end

In ActiveAdmin there is already a form in place to create an Account and a Membership from an existing User. That looks like this:

form do |f|
  ...
  f.inputs do
    f.has_many :memberships, heading: false, allow_destroy: true, new_record: "Add existing user" do |m|
      m.input :user_id, as: :searchable_select, ajax: { resource: User }
      m.input :role, as: :select, label: false, include_blank: false
    end
  end
  ...

What I'm trying to do is update the form to allow a way to create an Account and a new User with a Membership with a specific role. This is what I've tried so far (within the same form block as the one above):

f.inputs do
  f.has_many :users, heading: false, allow_destroy: true, new_record: "Add new user" do |u|
    u.input :name
    u.input :email, as: :string
    u.has_many :memberships, heading: false, allow_destroy: true, new_record: "Add membership" do |m|
      m.input :role, as: :select, label: false, include_blank: false
    end
  end
end

The form produced:

This doesn't work. If I don't fill in a role for the User's membership this will "work" and the before_validation in the Membership model will assign the User a Membership with role Admin. However, if I try to add a role to the User through the form and click "Create Account", then I am returned to the form where I see an error stating that Account must exist. This leads me to believe that the form is ignoring the second has_many that I've nested under f.has_many :users.

I've also tried approaching this by creating an input in the f.has_many :users block:

u.input :memberships, as: :select, label: "Role", include_blank: false, collection: Membership.roles

Instead of telling me that the Account must exist, this ignores any value I assign for the role, creates the User and assigns it a Membership with the role of Admin

How can I make this happen?

Upvotes: 3

Views: 967

Answers (1)

Piers C
Piers C

Reputation: 2978

When you add through the form this is performed using JavaScript that includes before and after creation hooks I don't have an example but look at the code and see if it helps.

Upvotes: 1

Related Questions