Step by Step Ruby on Rails

Ruby on Railsで実際にWebサイトを構築する手順をまとめています。

Ruby on Rails Tutorial ステータスフィードを実装

「Ruby on Rails Tutorial」のサンプルアプリをAngularJSとBootstrap3を使う形にして作成します。最後に、ステータスフィードを実装します。

以前の仮作成の段階では、現在ログインしているユーザーのマイクロポストを取得して表示していました。

今回は、現在のユーザーにフォローされているユーザーのマイクロポストと合わせて表示するようにします。

1)Rails側のSQL設定

①前回のコード

$ vi app/models/user.rb

  def feed
    Micropost.where("user_id = ?", id)
  end

②Ruby on Railsチュートリアルのコード

$ vi app/models/user.rb

  def feed
    Micropost.from_users_followed_by(self)
  end

$ vi app/models/micropost.rb

  def self.from_users_followed_by(user)
    followed_user_ids = "SELECT followed_id FROM relationships
                         WHERE follower_id = :user_id"
    where("user_id IN (#{followed_user_ids}) OR user_id = :user_id",
          user_id: user.id)
  end

③今回作成したコード

マイクロポスト一覧を表示する際、micropostsテーブルのカラム以外にユーザーID、ユーザー名、ユーザーのメールアドレスが必要です。

上記②のメソッドではユーザーIDは取得できますが、ユーザー名とメールアドレスはさらにusersテーブルをジョインして取得する必要があります。

直接コントローラ内からSQLを記述して、データを取得しました。

$ vi app/controllers/sessions_controller.rb

  def current_user
    remember_token = User.encrypt(cookies[:remember_token])
    current_user ||= User.find_by(remember_token: remember_token)
    if current_user
      gravatar_id = Digest::MD5::hexdigest(current_user.email.downcase)
      conn = ActiveRecord::Base.connection
      sql = "SELECT microposts.*,users.name,users.email " +
            "FROM microposts,users " +
            "WHERE (user_id IN (" +
            "SELECT followed_id FROM relationships WHERE follower_id = " +
            current_user.id.to_s + " )" +
            "OR user_id = " + current_user.id.to_s + " ) " +
            "AND microposts.user_id = users.id"
      feed = conn.select_all(sql)
      @user_info = {
        user: current_user,
        gravatar_url: "https://secure.gravatar.com/avatar/#{gravatar_id}",
        microposts: current_user.microposts,
        feed: feed,
        followed_users: current_user.followed_users,
        followers:  current_user.followers
      }
      render json: @user_info, status: :accepted
    else
      head :no_content
    end
  end

2)AngularJSビューの設定

$ vi app/assets/templates/static_pages/home.html.erb

<h3>Micropost Feed</h3>
<ol class="microposts">
  <li ng-repeat="mp in currentitems">
    <a href="/users/{\{mp.user_id}}">
      <img alt="{\{mp.name}}"
           src="https://secure.gravatar.com/avatar/{\{hash(mp.email)}}?s=60"
           class="gravatar"
      />
    </a>
    <a href="/users/{\{mp.user_id}}">{\{mp.name}}</a>
    <div>{\{mp.content}}</div>
    <small class="text-muted">Posted {\{mp.created_at | date:'medium'}}</small>
  </li>
</ol>