2

Railsで「仮想関係」(私が呼んでいるもの-実際の用語があるかどうかはわかりません)を実行しようとしています。これが私が持っているもので、間違いなく機能して いますアドレスbelongs_toBusinessおよびBusinesshas_manyAddressesアドレスには「カテゴリ」列があります:郵送または物理。理論的には、企業は各タイプをいくつでも持つことができますが、実際には、それぞれを1つだけ持っています。したがって、私のモデルは次のようになります。

class Address < ActiveRecord::Base
  belongs_to :business
end

class Business < ActiveRecord::Base
  has_many :addresses
  has_one  :physical_address, :class_name => 'Address', :conditions => ["category = ?", "Physical"]
  has_one  :mailing_address, :class_name => 'Address', :conditions => ["category = ?", "Mailing"]
end

したがって、2つの「仮想」has_oneがあるので、自分で分離する作業をしなくても、どちらか1つ( business.physical_addressまたはbusiness.mailing_addressとして)に簡単にアクセスできます。

今、私は似たようなことをしようとしていますが、has_many:throughを使用しています。これが私の新しいシナリオです。私は、参加との単純な多対多の関係を持っています。Aには多くのJがあり、Bにも多くのJがあり、JはABの両方に属しているとします。ただし、AにはJまでのBも多数あります。したがって、a.bsとしてそれらにアクセスできます。

ただし、Bのエントリにも「カテゴリ」があります。したがって、上記のBusiness / Addressの例と同様に、 Aに「仮想」のhas-one / many-through関係を設定したいので、 Bをカテゴリ別に手動で区切る必要はありません。私はこのようなことを試みました(Aがcategory ='Type 1'のBを1つだけ持っていると仮定します):

class A < ActiveRecord::Base
  has_many :js
  has_many :bs, :through => js
  has_one  :b_type1, :class_name => 'B', :through => :js, :conditions => ["category = ?", "Type 1"]
end

ただし、Aを検索すると、結果のオブジェクトにはb_type1プロパティが含まれていません。

私がやろうとしていることをすることさえ可能ですか?どんな助けでも大歓迎です。

編集:これをAdobe Flexフロントエンドにシリアル化する必要があります(RestfulXフレームワークを使用)。このスレッドによると、@ Andrewが以下に提案するように、メソッドだけを使用することはできません。結果として得られるオブジェクトは、多大な労力を費やさないと適切にシリアル化されないためです。

4

2 に答える 2

2

作成したhas_oneアソシエーションは、希望どおりに機能するはずですが、Railsは:b_type1からフィールドを推測できません。

クラス名を明示的に指定したのと同じように、ソースを指定してみてください。

has_one :b_type1, :class_name => 'B', :through => :js, :source => bs, :conditions => ["category = ?", "Type 1"]

私は同様のファインダーをテストしましたが、期待どおりに機能しました。

于 2011-06-14T04:35:20.817 に答える
1

これを解決するために私が考えることができる2つの「より簡単な」方法があります。

最初の方法:なぜこれらのメソッドを作成しないのですか?

あなたが与えた最初の例では、あなたのビジネスクラスでこれを試してください:

def physical_address
   self.address.where(:category => 'physical').first
end

ここで呼び出すbusiness.physical_addressと、アドレスオブジェクトが返されます。同じように、HABTMアソシエーションでこれを行うことができます。

class A < ActiveRecord::Base
  ...
  def type_1
    self.bs.where(:category=>'type_1').first
  end
  ...
end

ここで呼び出すa.type_1と、カテゴリが「Type_1」の単一のB(または複数ある場合は最初のB)が返されます。

2番目の方法:特定の「仮想関係」に複数の一致があると考えた場合は、これらの条件をスコープにすることができます。したがって、2番目の例では:

class B < ActiveRecord::Base
  ...
  scope :type_1 { where(:category=>'type_1') }
  ...
end

今、あなたが電話した場合、あなたa.bs.type_1.firstはあなたが探していたBを手に入れるでしょう。.firstスコープを1つしか持たない場合は、スコープに入れることもできます。

1つだけであることを強制するために、一意性の検証を作成て、特定の親オブジェクトを持つカテゴリの一意性を検証することもできます。

これらのオプションのいずれかを使用することは、これらの「仮想」関係を構築するよりも、問題を解決するための「レールウェイ」にはるかに近いように思われます。多分それは私だけです。

これを試してみて、何か問題があれば教えてください:)

于 2011-06-14T04:55:59.457 に答える