【问题标题】:Rails 2.3 dynamic has_many conditions based on other associationRails 2.3 基于其他关联的动态has_many条件
【发布时间】:2012-09-03 11:32:01
【问题描述】:

我有一个名为 Books 的 ActiveRecord 模型,它在 authors 上具有 has_one 关联,在 publishers 上具有 has_many 关联。所以下面的代码都很好

books.publishers

现在我有另一个 AR 模型,digital_publishers,它很相似,但如果本书作者回复 digital?,我想透明地使用它 - 让我用一些代码解释一下

normal_book = Book.find(1)
normal_book.author.digital? #=> false
normal_book.publishers #=> [Publisher1, Publisher2, ...]

digital_book = Book.find(2)
digital_book.digital? #=> true
digital_book.publishers #=> I want to use the DigitalPublishers class here

所以如果这本书的作者是数字的(作者是通过has_one :author 关联设置的,所以它不像在 books 表上有一个带有 SQL 条件的 has_many 那样简单),我仍然希望能够调用@987654332 @ 就可以了,但是要返回一个DigitalPublishers 的列表,所以我想要我的has_many 关联的一些条件,它首先检查这本书是否是数字的,如果是,使用DigitalPublishers 类而不是@ 987654336@班级。

我尝试使用以下代码使用after_find 回调:

after_find :alias_digital_publisher

def alias_digital_publisher
  if self.author.digital?
    def publishers
      return self.digital_publishers
    end
  end
end

但这似乎没有奏效。另外,我使用的是 Rails 2.3。

【问题讨论】:

  • 我已经解决了一个类似的多态关系问题(Book has_many publishers [Normal or Digital]),但使用的是 rails 3.0.1。所以我不知道该解决方案是否适用于 rails 2.3
  • 你能在这里添加键模型(书籍、作者、出版商)吗?你也在使用接受嵌套属性吗?

标签: ruby-on-rails associations has-many ruby-on-rails-2


【解决方案1】:

我需要有关该项目的更多信息才能真正提出建议,但这里有一些想法需要考虑:

1。出版商不应该属于书籍

我猜一个出版商可能与不止一本书相关联,因此它们属于书籍并没有多大意义。我会考虑

#Book.rb
has_many :publishers, :through=>:publications

2。将数字出版商存储在 publishers 表中

对于具有type 列的DigitalPublisher 的数字发布者使用单表继承 (STI),或者仅添加一个布尔值来指示发布者是否为数字发布者。

这样,您只需致电book.publishers,您就会获得可能是或可能不是数字的出版商,具体取决于分配的内容。

诀窍在于,您需要确保仅将数字出版商分配给具有数字作者的书籍。不过这对我来说很有意义。

3。 (或者)为发布者添加一个方法

def book_publishers
   author.digital? ? digital_publishers : publshers
end

我不太喜欢这个选项,我认为你最好将所有发布者放在一个表中。

【讨论】:

    【解决方案2】:

    查看 Rails Guides v-2.3.11 中的 section。特别注意以下几点:

    after_initialize 和 after_find 回调与其他回调有些不同。它们没有 before_* 对应物,注册它们的唯一方法是将它们定义为常规方法。如果您尝试使用宏样式的类方法注册 after_initialize 或 after_find,它们将被忽略。

    基本上,尝试将您的after_find 定义为

    def after_find
      ...
    end
    

    如果这不起作用,可能是因为图书的字段尚未初始化,因此请尝试使用after_initialize

    【讨论】:

      【解决方案3】:

      我的解决方案很简单。

      class Book < ActiveRecord::Base
      
          has_many :normal_publishers, :class_name => 'Publisher'
          has_many :digital_publishers, :class_name => 'DigitalPublisher'
      
          def publishers
              if self.digital?
                  self.digital_publishers
              else
                  self.normal_publishers
              end
          end
      
      end
      

      您仍然可以链接一些方法,例如book.publishers.countbook.publishers.find(...)

      如果你需要book.publisher_idsbook.publisher_ids=book.publishers=,你可以像book.publishers这样定义这些方法。

      以上代码适用于 Rails 2.3.12。

      更新:抱歉,我在发布此内容后注意到 klochner 的替代解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-01
        • 1970-01-01
        • 2017-04-21
        • 2014-07-08
        • 1970-01-01
        • 2011-06-23
        相关资源
        最近更新 更多