アソシエーションの拡張。

「学習する」というクラスには、主たるメソッドが二つあって、ですね。
「憶える」メソッドと、「学ぶ」メソッド、ですね。


で、「憶える」メソッドは、ぶっちゃけ、あまり楽しくない訳ですわwww
空き領域に、値を放り込むだけですから。


でも、「学ぶ」メソッドは、そりゃあ、もう、アレですよ。
頭の後ろっ側が、ピコーンって光りますよ。
コレこそが、学習することの醍醐味な訳ですよ。


でも、悲しいかな、年男も3度目になりますと、ですね。
脳の構造が硬直化してくるのか、中々、「学ぶ」ということが苦手になってくるようでして。


それは、やっぱり、これまで学んできたことが、経年によって、憶えたことに変わってくるからなんでしょう。
ロジックを学んで、そのロジックを実行してきたことが、やがて、「そのロジックに値を放り込めば、どうなる」ということを、憶えてしまうんですね。


だから、思考の幅が拡がらなくなっていくんですな。
思い込みが有する領域が拡がって、考える領域をどんどんと縮小化していく。
だって、その方が速いから。
新たにロジックを通すよりも、キャッシュされたものを出す方が、速いし楽だし。
往々に、それで正しい結果が得られることの方が多いから。
だから、己の中に蓄積されていないことを新たに身に付けようとしても、中々、身に付かないんだよね。


学ぶ前に、憶えたことで処理しようとするから。


ツマンネwww


で、なんでこんなに長い前フリをするか、というとですね。
まあ、実例なんですけどもwww、以下の通りのモデルが二つあってですね。

class User < ActiveRecord::Base
  has_many :asked,                :foreign_key => 'asked_user_id',
                                  :class_name => 'Friend',
                                  :dependent => :destroy
  has_many :was_invited,          :foreign_key => 'was_invited_user_id',
                                  :class_name =>'Friend',
                                  :dependent => :destroy do
  has_many :asked_friends,        :through => :asked,
                                  :source => :asked_to
  has_many :was_invited_friends,  :through => :was_invited,
                                  :source => :was_invited_from
end
class Friend < ActiveRecord::Base
  belongs_to :asked_to,   :foreign_key => :was_invited_user_id,
                                :class_name => "User"
  belongs_to :was_invited_from, :foreign_key => :asked_user_id,
                                :class_name => "User"
end


で、多対多の自己参照で関連付けされている訳ですわ。


んで、Friendモデルには、「state」というカラムがある訳ですよ。
で、User(hogehoge)が、Friendモデルで関連付けされているUserは、script/consoleだったら、

>> @user = User.find_by_nickname("hogehoge")
>> @user.asked_friends
>> @user.was_invited_friends

で、解る訳ですわ。
両者の論理籍をとれば、Friendモデルで結びつけられた、Userがまとめられる訳ですわ。

>> @friendships = @user.asked_friends & @user.was_invited_friends


で。
じゃあ、hogehogeとfugafugaが関連付けられたFriendオブジェクトのstatusは?

>> @friendship = Friend.find(:first, :conditions => { :asked_user_id => hogehoge.id, :was_invited_user_id => fugafuga.id})
>> @frindship.status

ですな。


じゃあ、Friendモデルで、statusがacceptedなものを集めるのは?

>> @friendships = Friend.find(:all, :conditions => {:state => "accepted"})


じゃあ、User(hogehoge)が関連付けられた、Friendオブジェクトは?


いやいや、悩んだ悩んだwww
そりゃあ、もう、無駄に悩んだよ。


Friendモデルから、asked_user_idかwas_invited_user_idにhogehoge.idが含まれているのを集めて...


いやいや、もう、集まってるんだよね。

>> @user.asked | @user.was_invited


なんで、こんなことに気が付かないの? 俺www
「asked」と「was_invited」が、唯の中間テーブルの役割でしかない、と、思い込んでるの。
外部から参照することが出来ない、と思い込んでやんの。


なんでだよっwww
普通に考えれば、間で値を抜くことが出来て、当たり前じゃんwww


バカじゃね? 俺。


今、ちょっと涙目だよwww
で。
こんなことも気が付かないから、「User(hogehoge)の関連付けられたFriendモデルの中で、stateがacceptedなものを集める」っていうのを考える時に、すっっっっごい手間なことを考えてしまうんだよね。
「んあああああ、総当たりでループ回して、判定して、分岐して、ヒットしたヤツを変数に積むか...」って。


いや、ね?
それ、激しくダサいでしょ?
超低レベルじゃない。


そりゃあ、ね? 内部的にとか、ローレベルなところで考えれば、総当たりループしているような処理なんて、山ほどあるでしょうよ。
でも、それじゃあ、超簡単便利お気楽スクリプトを使う意味なんて、ない訳ですよ。
それこそ、アセンブラ書いとけよ、って話ですよ。


バカでも出来ることを、エレガントにやってこその、プログラミングって云うもんでしょ?


で、見出しになる訳ですわ。
煙草をふかしながら、RailsによるアジャイルWebアプリケーション開発 第2版を眺めていたら、314ページ辺りで、この見出しですよ。


「うわああああっ」って、声上げたよwww

んで、こんな感じに変わりました。

class User < ActiveRecord::Base
  has_many :asked_friendships,        :foreign_key => 'asked_user_id',
                                      :class_name => 'Friend',
                                      :dependent => :destroy do
                                        def with_state(state)
                                          find(:all, :conditions => { :state => state })
                                        end
                                      end
  has_many :was_invited_friendships,  :foreign_key => 'was_invited_user_id',
                                      :class_name =>'Friend',
                                      :dependent => :destroy do
                                        def with_state(state)
                                          find(:all, :conditions => { :state => state })
                                        end
                                      end
  has_many :asked_friends,            :through => :asked_friendships,
                                      :source => :asked_to
  has_many :was_invited_friends,      :through => :was_invited_friendships,
                                      :source => :was_invited_from
end

これで、わざわざ自前でコレクション作らなくても、なんやかんやと持ってこれるようになりました。

>> @user.asked_friends

で、該当するUserオブジェクト、

>> @user.asked_friendships

で、該当するFriendオブジェクトを。

>> @user.asked_friendships.with_state("accepted")

で、該当するstateがacceptedなFriendオブジェクトをゲット出来ますな。


...あ〜あ。
俺、超涙目www
打ち拉がれました、なあ...
歳をとる、って云うことは、こういうことなんだな...


キャッシュされているものが、無駄足を踏む結果を生んだり、全く役に立たなかったりなんかする時の、この、無力感ったら、ありゃあしませんよwww


悲しいねwww