尽管 has_one 为 has_one 构建方法
build methods for has_one though has_one
Rails 5.1.2
Ruby2.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
但是,尝试使用等效的 has_one
构建方法构建嵌套的 promotion
关联会导致 NoMethodError (undefined method 'build_promotion' for #<Subscriber:0x00007f9042cbd7c8>)
错误
s = Subscriber.new
s.build_promotion
但是,这确实有效:
s = Subscriber.new
s.build_subscription
我觉得人们应该期望以与构建 has_many
相同的方式构建嵌套 has_one
关系是合乎逻辑的。
这是错误还是设计使然?
检查代码,当您调用 has_one 时,它仅在反射为 "constructable"[ 时创建 build_
、create_
和 create_..!
方法=21=]
define_constructors(mixin, name) if reflection.constructable?
现在,检查 constructable?
方法,它 returns calculate_constructable
https://github.com/rails/rails/blob/ed1eda271c7ac82ecb7bd94b6fa1b0093e648a3e/activerecord/lib/active_record/reflection.rb#L452
的结果
对于 HasOne class,如果您使用 :through
选项 https://github.com/rails/rails/blob/ed1eda271c7ac82ecb7bd94b6fa1b0093e648a3e/activerecord/lib/active_record/reflection.rb#L723
,它 returns 为假
def calculate_constructable(macro, options)
!options[:through]
end
所以,我想说这不是错误,它是设计使然的。虽然我不知道原因,也许感觉合乎逻辑,但我想有些事情要考虑并不是那么简单。
Rails 5.1.2 Ruby2.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
但是,尝试使用等效的 has_one
构建方法构建嵌套的 promotion
关联会导致 NoMethodError (undefined method 'build_promotion' for #<Subscriber:0x00007f9042cbd7c8>)
错误
s = Subscriber.new
s.build_promotion
但是,这确实有效:
s = Subscriber.new
s.build_subscription
我觉得人们应该期望以与构建 has_many
相同的方式构建嵌套 has_one
关系是合乎逻辑的。
这是错误还是设计使然?
检查代码,当您调用 has_one 时,它仅在反射为 "constructable"[ 时创建 build_
、create_
和 create_..!
方法=21=]
define_constructors(mixin, name) if reflection.constructable?
现在,检查 constructable?
方法,它 returns calculate_constructable
https://github.com/rails/rails/blob/ed1eda271c7ac82ecb7bd94b6fa1b0093e648a3e/activerecord/lib/active_record/reflection.rb#L452
对于 HasOne class,如果您使用 :through
选项 https://github.com/rails/rails/blob/ed1eda271c7ac82ecb7bd94b6fa1b0093e648a3e/activerecord/lib/active_record/reflection.rb#L723
def calculate_constructable(macro, options)
!options[:through]
end
所以,我想说这不是错误,它是设计使然的。虽然我不知道原因,也许感觉合乎逻辑,但我想有些事情要考虑并不是那么简单。