I have a User
model which can have many child accounts. I have set up the model as below
class User < ApplicationRecord
has_many :child_accounts, class_name: "User", foreign_key: "parent_account_id"
belongs_to :parent_account, class_name: "User", optional: true
end
I have created a ChildAccountsController
to handle the child accounts creation etc. and defined routes as below.
resources :users do
resource :child_accounts
end
But I can get form_with
to work in this situation. as
form_with(model: [current_user, @child_account], local: true) do
#...
end
form_with infers the url from the model class since both of them are User. the path it infers user_user_path
instead of user_child_accounts_path
.
So, is there a rails way to create forms with self joins? Or do I have manually handle this case?
To start with you have a pluralization error:
resources :users do
resources :child_accounts
end
resource
is used to declare singular resources .
But the polymorphic route helpers will not be able route to that path automatically anyways, when you pass model instances to form_for
, form_with
, link_to
and button_to
they deduce the name of route helper method by calling #model_name
and using the methods of ActiveModel::Naming
. Since @child_account
is an instance of User you get user_users_path
. The polymorphic routing helpers are not aware of your associations.
It does not matter at all here if you use form_for
or form_with
as both use the exact same methods to figure out a path from a model or array of models.
You either need to explicitly pass the url:
form_with(model: @child_account, url: user_child_accounts_path(current_user), local: true) do
#...
end
Or use single table inheritance :
class AddTypeToUsers < ActiveRecord::Migration[6.0]
def change
change_table :users do |t|
t.string :type
end
end
end
class User < ApplicationRecord
has_many :child_accounts,
foreign_key: "parent_account_id",
inverse_of: :parent_account
end
class ChildAccount < User
belongs_to :parent_account,
class_name: "User",
inverse_of: :child_accounts
end
class ChildAccountsController < ApplicationController
def new
@child_account = current_user.child_accounts.new
end
def create
@child_account = current_user.child_accounts.new(child_account_params)
# ...
end
private
def child_account_params
params.require(:child_account)
.permit(:foo, :bar, :baz)
end
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.