0

レール 5.1.2 ルビー 2.5.3

この関係を暗示する方法は複数あることは理解していますが、この質問は、実際の問題を解決するというよりも、以下が機能しない理由に関するものです。

has_many設定

class Subscriber < ApplicationRecord
  has_many :subscriptions, inverse_of: :subscriber
  has_many :promotions, through: :subscriptions, inverse_of: :subscriptions

  accepts_nested_attributes_for :subscriptions
  accepts_nested_attributes_for :promotions
end

class Subscription < ApplicationRecord
  belongs_to :subscriber, inverse_of: :subscriptions
  belongs_to :promotion, inverse_of: :subscriptions
end

class Promotion < ApplicationRecord
  has_many :subscriptions, inverse_of: :promotion
  has_many :subscribers, through: :subscriptions, inverse_of: :subscriptions

  accepts_nested_attributes_for :subscriptions
  accepts_nested_attributes_for :subscribers
end

リレーションシップを使用するように設定されている上記のSubscriberモデルでは、次のように動作します。has_many

s = Subscriber.new
s.subscriptions.build
# OR
s.promotions.build

それに続いて、私は関係Subscriberと同じように振る舞うことを期待しますhas_one

has_one設定

class Subscriber < ApplicationRecord
  has_one :subscription, inverse_of: :subscriber
  has_one :promotion, through: :subscription, inverse_of: :subscriptions

  accepts_nested_attributes_for :subscription
  accepts_nested_attributes_for :promotion
end

class Subscription < ApplicationRecord
  belongs_to :subscriber, inverse_of: :subscription
  belongs_to :promotion, inverse_of: :subscriptions
end

class Promotion < ApplicationRecord
  has_many :subscriptions, inverse_of: :promotion
  has_many :subscribers, through: :subscriptions, inverse_of: :subscription

  accepts_nested_attributes_for :subscriptions
  accepts_nested_attributes_for :subscribers
end

promotionただし、同等のhas_oneビルド メソッドを使用してネストされた関連付けをビルドしようとすると、NoMethodError (undefined method 'build_promotion' for #<Subscriber:0x00007f9042cbd7c8>)エラーが発生します。

s = Subscriber.new
s.build_promotion

ただし、これは機能します。

s = Subscriber.new
s.build_subscription

has_oneネストされた関係を構築するのと同じ方法で構築することを期待するのは当然だと思いますhas_many

これはバグですか、それとも仕様ですか?

4

1 に答える 1

1

コードを確認すると、 has_one を呼び出すと、リフレクションが「構築可能」である場合にのみ、 build_create_およびメソッドが作成されますcreate_..!

https://github.com/rails/rails/blob/b2eb1d1c55a59fee1e6c4cba7030d8ceb524267c/activerecord/lib/active_record/associations/builder/singular_association.rb#L16

define_constructors(mixin, name) if reflection.constructable?

constructable?今、メソッドをチェックすると、 calculate_constructable https://github.com/rails/rails/blob/ed1eda271c7ac82ecb7bd94b6fa1b0093e648a3e/activerecord/lib/active_record/reflection.rb#L452の結果が返されます

HasOne クラスの場合、:throughオプションhttps://github.com/rails/rails/blob/ed1eda271c7ac82ecb7bd94b6fa1b0093e648a3e/activerecord/lib/active_record/reflection.rb#L723を使用すると、false が返されます。

def calculate_constructable(macro, options)
  !options[:through]
end

ですから、これはバグではなく、設計上そのように作られていると言えます。理由はわかりませんが、おそらく論理的に感じるかもしれませんが、それほど単純ではない考慮すべき点がいくつかあると思います.

于 2018-11-10T22:49:01.903 に答える