2

と呼ばれる ActiveRecord モデルがBooksあり、これには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

しかし、これはうまくいかなかったようです。また、Rails 2.3 を使用しています。

4

3 に答える 3

3

私は本当に推薦をするためにプロジェクトについてのより多くの情報が必要です、しかしここに考慮すべきいくつかの考えがあります:

1.出版社は本に所属すべきではありません

出版社は複数の本にリンクされている可能性があるので、それらが本に属していることはあまり意味がありません。私は考えます

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

2.デジタルパブリッシャーをパブリッシャーテーブルに保存します

typeの列を持つデジタルパブリッシャーには単一テーブル継承(STI)を使用するDigitalPublisherか、パブリッシャーがデジタルであるかどうかを示すブール値を追加します。

このようにすると、に電話をかけるだけbook.publishersで、割り当てられたパブリッシャーに応じて、デジタルである場合とそうでない場合があるパブリッシャーを取得できます。

秘訣は、デジタル出版社だけがデジタル著者の本に割り当てられるようにする必要があるということです。しかし、これは私には理にかなっています。

3.(または)パブリッシャー向けのメソッドを追加します

def book_publishers
   author.digital? ? digital_publishers : publshers
end

私はこのオプションのファンではありません。すべての発行元を1つのテーブルにまとめた方がよいと思います。

于 2012-10-10T20:35:29.213 に答える
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

上記のコードはRails2.3.12で機能します。

更新:申し訳ありませんが、これを投稿した後、klochnerの代替ソリューションに気づきました。

于 2012-10-12T14:21:18.977 に答える
1

Rails Guides v-2.3.11 のこのセクションをご覧ください。特に、次の点に注意してください。

after_initialize および after_find コールバックは、他のコールバックとは少し異なります。before_* に対応するものはなく、それらを登録する唯一の方法は、それらを通常のメソッドとして定義することです。マクロ スタイルのクラス メソッドを使用して after_initialize または after_find を登録しようとすると、それらは単に無視されます。

after_find基本的に、あなたを次のように定義してみてください

def after_find
  ...
end

それでもうまくいかない場合は、ブックのフィールドが初期化されていない可能性があるため、after_initialize代わりに試してください。

于 2012-10-09T16:48:01.363 に答える