Rails 2.3动态has_many条件基于其他关联

时间:2012-09-03 11:32:02

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

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

bookspublishers

现在我有另一个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那么简单),我仍然希望能够调用.publishers上有DigitalPublishers,但是返回has_many的列表,所以我希望我的DigitalPublishers关联上有一些条件,首先检查这本书是否为数字,如果是,请使用Publishers类,而不是after_find类。

我尝试使用以下代码使用after_find :alias_digital_publisher def alias_digital_publisher if self.author.digital? def publishers return self.digital_publishers end end end 回调:

{{1}}

但这似乎并没有成功。另外,我正在使用Rails 2.3。

3 个答案:

答案 0 :(得分:3)

我需要有关该项目的更多信息才能真正提出建议,但需要考虑以下几点:

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

我不是这个选项的粉丝,我认为你最好让所有发布者都在一个表中。

答案 1 :(得分:1)

从Rails Guides v-2.3.11中查看此section。特别注意以下内容:

  

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

基本上,请尝试将after_find定义为

def after_find
  ...
end

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

答案 2 :(得分:1)

我的解决方案很简单。

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的备用解决方案。