Rails 1.1以降のActiveRecordではhas_and_belongs_to_manyの代わりにhas_many :throughを使うのがトレンド。これはこれで便利なのだけれど、Activity Based Datamodel式のテーブル構造を使うためにはやっぱりhas_one :throughも欲しい。
本家のMLでは7月24日の"belongs_to :through?"とかいうスレッドでdelegate使えとか言われてる。でも、その場合発行されるSQLが効率悪そうで嫌だ。やっぱり結合して一気に持って来たい。
で、作ってみた。プラグインでも、environments.rbに直接書き込みでも好きなようにインストールしてください。暫定版だし。
早い話が、こう書きたいわけね。
class Member < ActiveRecord::Base has_one :membership has_one :group, :through => :membership end class Group < ActiveRecord::Base has_many :memberships has_many :members, :through => :memberships end class Membership < ActiveRecord::Base belongs_to :member belongs_to :group end ... alice = Member.find(1) alice.group # instead of alice.membership.group :-)
class ActiveRecord::Associations::HasOneThroughAssociation < ActiveRecord::Associations::HasOneAssociation
private
def construct_sql
@finder_sql = "#{@reflection.through_reflection.table_name}.#{@reflection.through_reflection.primary_key_name} = #{@owner.quoted_id}"
@finder_sql << " AND (#{conditions})" if conditions
end
def find_target
@reflection.klass.find(:first,
:select => @reflection.options[:select] || "#{@reflection.table_name}.*",
:conditions => @finder_sql,
:order => @reflection.options[:order],
:include => @reflection.options[:include],
:joins => "LEFT OUTER JOIN #{@reflection.through_reflection.table_name} " +
" ON #{@reflection.through_reflection.table_name}.#{@reflection.source_reflection.primary_key_name} " +
" = #{@reflection.table_name}.#{@reflection.klass.primary_key}"
)
end
end
module ActiveRecord::Associations::ClassMethods
def has_one_with_through(association_id, options = {})
if options[:through]
reflection = create_has_one_through_reflection(association_id, options)
association_accessor_methods(reflection, ActiveRecord::Associations::HasOneThroughAssociation)
else
has_one_without_through(association_id, options)
end
end
alias_method :has_one_without_through, :has_one
alias_method :has_one, :has_one_with_through
private
def create_has_one_through_reflection(association_id, options)
options.assert_valid_keys(
:class_name, :foreign_key, :remote, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as, :through
)
create_reflection(:has_one, association_id, options, self)
end
end
ありがとうございます。
欲しいっていってる人が結構いたので作っちゃいました。
最近この辺を丁度悩んでたのでナイスタイミングです!
FKは誰が持つべき?テーブルの粒度は?ABDは究極の解?etc...
ただ無かっただけで、coreが嫌ってるということはないと思います。
是非ともプラグイン化きぼん!(コピペで済むモノでも敷居が低くなる説)
スバラシス!Yuguiたん、カワユス!
> coreが嫌ってるということはないと思います。
舞波さんキタ━━━━━━━━(゜∀゜)━━━━━━━━━!!
そうですか。私の被害妄想ですか。ありがとうございます。
今度英語をタイプする気力があるときにIRCで「入れる気ない?」って聞いてみようと思います。
よくわからない理由により、コメントが即座には反映されないかもしれませんか゛、ボタンを押して元の画面に戻ってきたならたぶん正しく送信されています。
ktkr
超GJ!!