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 回答