我有一个名为Books
的ActiveRecord模型,has_one
上的authors
关联和has_many
上的publishers
关联。所以下面的代码都很好
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那么简单),我仍然希望能够调用.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。
答案 0 :(得分:3)
我需要有关该项目的更多信息才能真正提出建议,但需要考虑以下几点:
我猜测出版商可能会链接到不止一本书,因此它们属于书籍并不是很有意义。我会考虑
#Book.rb
has_many :publishers, :through=>:publications
对type
列为DigitalPublisher
的数字发布商使用单表继承(STI),或者只添加一个表示发布商是否为数字的布尔值。
通过这种方式,您只需拨打book.publishers
,就可以获得可能是也可能不是数字的发布商,具体取决于分配的内容。
诀窍在于,您需要确保仅将数字出版商分配给拥有数字作者的图书。这对我来说很有意义。
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.count
,book.publishers.find(...)
。
如果您需要book.publisher_ids
,book.publisher_ids=
,book.publishers=
,则可以定义这些方法,例如book.publishers
。
以上代码适用于Rails 2.3.12。
更新:对不起,我在发布此消息后发现了klochner的备用解决方案。