【问题标题】:build methods for has_one though has_onehas_one 虽然 has_one 的构建方法
【发布时间】:2018-11-10 21:40:00
【问题描述】:

导轨 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

在上面设置为使用has_manySubscriber 模型中,以下关系将起作用:

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

之后,我希望 Subscriberhas_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

但是,尝试使用等效的 has_one 构建方法构建嵌套的 promotion 关联会导致 NoMethodError (undefined method 'build_promotion' for #&lt;Subscriber:0x00007f9042cbd7c8&gt;) 错误

s = Subscriber.new
s.build_promotion

但是,这确实有效:

s = Subscriber.new
s.build_subscription

我认为人们应该期望像构建has_many 一样构建嵌套的has_one 关系是合乎逻辑的。

这是一个错误还是设计使然?

【问题讨论】:

    标签: ruby-on-rails has-one-through


    【解决方案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
    

    所以,我会说这不是错误,它是设计使然。虽然我不知道原因,也许感觉合乎逻辑,但我想有些事情要考虑并不那么简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多