Ruby on Rails Tutorial (21)

朝練メモ。継続は 11.1.3 でした。

11.1.3 Validations

relationship な validate の試験を spec/models/relationship_spec.rb に。

  describe "when followed id is not present" do
    before { relationship.followed_id = nil }
    it { should_not be_valid }
  end

  describe "when follower id is not present" do
    before { relationship.follower_id = nil }
    it { should_not be_valid }
  end

relationship なオブジェクトが存在する場合、両方とも nil はあり得ないですね。試験 red を確認した上で model に盛り込み。

class Relationship < ActiveRecord::Base
  attr_accessible :followed_id

  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"

  validates :follower_id, presence: true
  validates :followed_id, presence: true
end

試験 green 確認。確かにこの節は straightforward でしたね。

11.1.4 Followed users

spec/models/user_spec.rb に以下な試験を追加とのこと。

  it { should respond_to(:relationships) }
  it { should respond_to(:followed_users) }

とりあえずこんな属性はありません。ので試験は当然 red 終了となります。で、属性の追加なんですが、belongs_to が followed になってるので (?) 通常なら以下な形になるんだけど

has_many :followeds, through: :relationships

これはあまりにも、なので以下な形で記述、ってことで良いのかどうか。

  has_many :followed_users, through: :relationships, source: :followed

これで試験 green 終了を確認してます。
そして following な関係を結ぶための utility method として follow! を云々とありますね。あるいは following? も、とのこと。spec/models/user_spec.rb に諸々追加されていますね。
まず、メソドの存在チェックで以下。

  it { should respond_to(:followed_users) }
  it { should respond_to(:following?) }
  it { should respond_to(:follow!) }
b||<
そして動作の確認で以下。
>||
  describe "following" do
    let(:other_user) { FactoryGirl.create(:user) }
    before do
      @user.save
      @user.follow!(other_user)
    end

    it { should be_following(other_user) }
    its(:followed_users) { should include(other_user) }
  end

be_following とかどっから来たのかアレ。:followed_users ってのもですね。とりあえず盛り込んで試験 red 確認。
で、app/models/user.rb に以下のメソド定義を盛り込み。

  def following?(other_user)
    relationships.find_by_followed_id(other_user.id)
  end

  def follow!(other_user)
    relationships.create!(followed_id: other_user.id)
  end

で、試験実行して green 終了確認。be_following て何だ。つうかこいつが following? を呼び出して、ってことなのかな。rspec 関連確認必要。
つうか上の following な試験は全般的に不思議な部分が沢山ありますので別途確認の方向で。あと、relationships 云々も確認しといた方が良さげ。11.1.4 の最後までヤッてから確認入れます。
unfollow! も必要ってことで以下な試験を追加。

    describe "and unfollowing" do
      before { @user.unfollow!(other_user) }

      it { should_not be_following(other_user) }
      its(:followed_users) { should_not include(other_user) }
    end

試験 red 確認後に以下を盛り込み。

  def unfollow!(other_user)
    relationships.find_by_followed_id(other_user.id).destroy
  end

試験 green 確認。user_spec だけでスデに 41 個も試験があるのか。とりあえずここでエントリ投入します。rspec 云々については追記の方向で。

rspec 関連確認

user_spec.rb ちょっとだけおさらいしてみます。全般をがっつり掘削しつつ復習するのは全部写経が終了してから、と思っています。
とりあえず user_spec.rb では

  before do
    @user = User.new(name: "Example User", email: "user@example.com", 
                     password: "foobar", password_confirmation: "foobar")
  end

  subject { @user }

てのが先頭で記述されてて subject は基本的に @user なんですね。その上で今回追加したソレだと、とりあえず

  describe "following" do
    let(:other_user) { FactoryGirl.create(:user) }
    before do
      @user.save
      @user.follow!(other_user)
    end

    it { should be_following(other_user) }

other_user を用意した上でそれを follow! してます。@user.save する根拠はとりあえずスルーします。
で、@user.following?(other_user) であることを確認しているものと類推。
次の試験もなかなかアレ。

    its(:followed_users) { should include(other_user) }

これって @user の followed_users な属性が other_user を含んでいるべき、というソレを試験してるのか。its すばらです。あと include は followed_users な配列に other_user なオブジェクトが include? であることを確認しているのか。
unfollow! な試験は逆を確認してますね。成程。