【问题标题】:Rails associations with polymorphism and abstract classesRails 与多态性和抽象类的关联
【发布时间】:2019-06-12 18:20:10
【问题描述】:

这个真的让我摸不着头脑。我正在处理与多个类相关的多态关系,这些类都继承自一个抽象类。这运行良好,但是当我尝试从多态关系访问关联对象时遇到错误。这是我的实现:

class Foo < ApplicationRecord
  belongs_to :options, polymorphic: true
  accepts_nested_attributes_for :options

  def build_options(params)
    self.options = options_type.constantize.new(params)
  end
end

module Mod
  class Option < ApplicationRecord
    self.abstract_class = true
    has_one :foo, as: :options

    self.table_name_prefix
      'foo_'
    end
  end

  class Bar < Options
  end

  class Baz < Options
  end
end

到目前为止,这一直运行良好,但是当我尝试这样的事情时遇到了一个问题:

Bar.first.foo

我收到此错误:

ActiveRecord::AssociationNotFoundError (Association named 'foo' was not found on Foo::Bar; perhaps you misspelled it?)

让我觉得奇怪的是,如果我打电话给Bar.first.methods,我会选择:foo

知道我需要做什么来解决这个问题并仍然使用Options 类继承吗?我知道我可以在子类上定义has_one,但它适用于Options 的所有子类,如果我可以将关联保留在那里,我愿意。

编辑:情节变厚了!在玩了一会儿之后,我现在意识到有些子类有关联工作,但有些没有。我似乎也找不到正在工作的课程与不工作的课程之间的任何区别。

【问题讨论】:

  • 你会把你的代码库推送到 Github 的公共存储库吗?
  • 这是我公司的私人仓库,所以很遗憾,我不能。
  • 您可以创建一个仅包含关联模型的示例代码库
  • 危险信号:(1) Foo::Bar 在错误消息中。您是否定义了另一个 Bar 类?我希望看到Mod::Bar 的书面内容。 (2) 是class Option 还是class Options?该协会暗示它应该是后者。 (3) table_name_prefix 是干什么用的? (你是否错过了def?)
  • (4) 当您说Bar.first 时,您的意思是Mod::Bar.first?我正在尝试最低限度地复制您的代码,并确认一旦嵌套在模块中,如果没有模块命名空间,我就无法单独引用 Bar

标签: ruby-on-rails polymorphic-associations


【解决方案1】:

您可能遇到了变形问题,belongs_to 应该是单数而不是复数(option 而不是 options)。将has_one :foo, as: :options 更改为as: :option 也是如此。

table_name_prefix 在这里不是必需的,在 STI 中所有类都将共享同一个表。

这段代码对我来说没有问题:

# app/models/foo.rb
class Foo < ApplicationRecord
  belongs_to :option, polymorphic: true
end

# app/models/mod/option.rb
module Mod
  class Option < ApplicationRecord
    self.abstract_class = true
    has_one :foo, as: :option

    self.table_name = "mod_options"
  end
end

# app/models/mod/baz.rb
module Mod
  class Baz < Option
  end
end

# app/models/bar.rb
module Mod
  class Bar < Option
  end
end

【讨论】:

  • 所有子类实际上在数据库中都有自己的表,因为每个子类都附加了不同的数据。例如,其中一个包含有关特定时间量的信息,另一个引用来自不同类的特定对象。不过,我明白您对拐点的意思,belongs_to :options 在技术上并不是正确的拐点。我会试试belongs_to :option,看看是否有帮助。
【解决方案2】:
# /app/models/user.rb
class User < ActiveRecord::Base
  has_one :profile, as: :profileable, dependent: :destroy
end

# /app/models/business.rb
class Business < ActiveRecord::Base
  has_one :profile, as: :profileable, dependent: :destroy
end

# /app/models/profile.rb
class Profile < ActiveRecord::Base
  belongs_to :profileable, polymorphic: true
end

参考上面的例子。

【讨论】:

  • 这并不反映我在问题中的例子。请重新阅读我的问题。
猜你喜欢
  • 1970-01-01
  • 2020-08-01
  • 1970-01-01
  • 2019-03-14
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多