0

Addressというポリモーフィックモデルがあります。私が達成しようとしているのは、他のモデル(たとえば、ユーザー)にバインドされた多くのアドレスをヘビーにすることですが、それでも1つしかない場合と同じように使用し、タイプごとに区別してみてください。

私のプロジェクトは1つのアドレスのみを使用するように設計されているため、のようなコードUser.first.addressUser.first.address=...何もできないコードがたくさんあります。

これが一種の例です:

|id|addressable_type|addressable_id| type   | street |
  1|User            |1             | first  | Foo
  2|User            |1             | second | Bar  
  3|User            |1             | NULL   | Other  

そして私がしたいのは:

User.find(1).address(:second)

どちらを返す必要があります<Address street:"Bar">

User.find(1).address

これはを返す必要<Address street:"Other">User.find(1).addressesありますが、オブジェクトのコレクションを返す必要があります。

私はコードの一部を使用して、モデルにアドレス動作を追加します。

    module Ext::Models::Addressable

def self.included(mod)
    super
    mod.class_eval do
      def self.acts_as_addressable          
        include InstanceMethods

        # Use has_many :delete_all for better performance
        has_many :addresses, :as => :addressable, :dependent => :delete_all
        has_one :address, :as => :addressable
      end
    end
end

module InstanceMethods
            # I tried with this, but this doesn't even allow me to start rails becauses raises "there is no address method"  
    def address_with_type(type = nil)
        if type
            self.addresses.find(:first, :conditions => ["type = ?", type.to_s])
        else
            address_without_type
        end
    end
    alias_method_chain :address, :type
end
end

Rails2.3.14とRuby1.9.2を使用しています。

これが可能であれば、特定のモデル(たとえばユーザー)の新しいアドレスを作成するための最良の方法も知りたいです。

前もって感謝します。

解決

私はすべての可能性を絞り込みました、そして現在プロジェクトでは2つのタイプのアドレスしかありません。アプローチを大幅に簡素化することができました。現在、私のようにself.included見えます:

has_many :addresses, :as => :addressable, :dependent => :delete_all
has_one :address, :as => :addressable, :conditions => {:type => nil}
has_one :foo_address, :class_name => 'Address', :as => :addressable, :conditions => {:type => "foo"}

そして今、私はこのような新しいオブジェクトを構築することができます: user.build_address(:street => "abc")そしてuser.build_foo_address(:street => "def")、まさに私が必要としているものです。

4

1 に答える 1

0

そのようにデフォルトと予想される動作をオーバーライドすることには少し注意が必要です。許せない理由があるのuser.address

あなたがどのような問題を解決しているのか正確にはわかりませんが、次のようなことができるかもしれません:

class User < ActiveRecord::Base
  has_many :addresses, :as => :addressable, :dependent => :delete_all

  def address(only_type = "primary")
    addresses.find_first("type" => only_type)
  end

  def address=(addr)
    addresses.delete address
    addresses << addr.update_attribute("type", "primary")
  end

  def build_address(attr)
    addresses.delete address
    addresses.build attr.merge("type" => "primary")
  end

  def create_address(attr)
    addresses.delete address
    addresses.create attr.merge("type" => "primary")
  end
end

私はこのコードをテストしておらず、Rails 2 に慣れていないので、インスピレーションとして使用してください。モジュール化するために、いくつかのメタ要素でラップすることができます。ところで、「タイプ」を使用している場合は、STI が発生します。それが必要かどうかはわかりません。

于 2012-10-23T22:15:57.330 に答える