cancancan icon indicating copy to clipboard operation
cancancan copied to clipboard

undefined method `#{parent_name}=' for singleton associations

Open heaven opened this issue 3 years ago • 0 comments

Steps to reproduce

The code below produces this error when assigning the parent to the new resource using the :through parameter that points to a method in the controller.

class Member < ApplicationRecord
  has_one :subscription, class_name: "Billing::Subscription", inverse_of: :member
end

class Billing::Subscription < ApplicationRecord
  belongs_to :member, inverse_of: :subscription
end

class API::V1::Billing::SubscriptionsController < API::APIController
  load_and_authorize_resource class: "Billing::Subscription", through: :current_member, singleton: true

  def create
    @subscription.save!
    respond_with(@subscription, location: api_v1_billing_subscription_url)
  end
end

Expected behavior

@subscription.member should have been assigned, instead of @subscription.current_member.

There are a few workarounds to this. First, there's the inverse_of parameter on associations, so it's possible to find the reflection and get the proper name. Additionally, when inverse_of is present, you probably don't have to assign the parent manually but rather use build_#{resource_name}.

Another option is to add a new inverse_of option to load_and_authorize_resource method, where we can explicitly specify the parent name.

Actual behavior

undefined method `current_member=' for #<Billing::Subscription id: nil, member_id: nil, price_id: 1, status: "created", ...

System configuration

Rails version: 7.0.3 Ruby version: ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x86_64-darwin20] CanCanCan version: 3.3.0, 3.4.0

heaven avatar Jul 04 '22 16:07 heaven