Association
あるUserの投稿(micropost)を取得したい場合
@id = User.first.id
@micropost = Micropost.find_by(id: @id)
これを簡潔にするために
has_many :microposts
とすると、Userが複数の投稿を持っているということが宣言され、
User.first.microposts
の一行で、先の動作が可能になる
同様に
Micropost.find_by(user_id: @user.id) == user.microposts
Micropost.new(user_id: @user.id) == user.microposts.build
# 例えば
user.microposts.build(content: "----")
# 新規投稿が可能
Test
test "should be valid" do # micropostsの形式は正しいか
assert @micropost.valid?
end
test "user id should be present" do #user_idがnilのmicropostははじかれているか
@micropost.user_id = nil
assert_not @micropost.valid?
end
その投稿を行ったUserの情報を取得したい場合、Micro => User
belongs_to :user
とすることで可能(ex. Microposts.first.user
user controller show view のPartialで
-> rendering _micropost.html そのUserの投稿を表示する,
deleteリンクの作成 DELETE /micropostsに送られる
-> destroy action
static_pages controller home action @micropost = current_user.micropost.build()
static_pages controller home view のPartial shared/user_info
-> Userの名前など
static_pages controller home view のPartial shared/micropost_form
-> micropost_form.html 投稿機能
form_for(@microposts) POST /micropostsに送られる
-> micropost controller create action
DBのcontentカラムに投稿を保存
Profileページの右側の作成
Micropostsを表示する
表示する内容は
<li id="micropost-<%= micropost.id %>">
# 画像の表示、micropost.user、リンク先は
<%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
# micropostを行ったuserのnameと理解
<span class="user"><%= link_to micropost.user.name, micropost.user %></span>
# 投稿内容
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
# その投稿が作成された日から何日前かを表示
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
</li>
user.micropost とmicropost.userが理解しづらいときは文章にする良い
userの投稿(micropost)は
投稿(micropost)したuserは
def create
@micropost = current_user.microposts.build(micropost_params)
# 現在ログインしているユーザーの投稿を新規作成
# micropost_params = content: params[:content] 安全なので左で
if @micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def micropost_params
params.require(:micropost).permit(:content)
# user_idはなく、contentだけ
end
実際の仕様に合わせてログインしているときとしていない時で、Topページが変わるようにする
<% if logged_in? %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= render 'shared/user_info' %> # rendering _user_infoを新たに作る
</section>
<section class="micropost_form">
<%= render 'shared/micropost_form' %> # rendering _micropost_formを作る
</section>
</aside>
</div>
<% else %>
..(略)
# 今までのTopページ
form_forの引数のPartial
object: f.objectは上級者向けなので、実戦で使えそうな時に改めて理解
form_forの引数が何であっても使えるようにする
タイムラインの設計 -feed機能 難しい
def feed
Micropost.where("user_id = ?", id)
# whereの挙動、各モデルから対応するSQLを一部だけ追加する(?
# 難しいが、自分が投稿したものが戻り値として返ってくるという機能がある
end
def home
if logged_in?
@micropost = current_user.microposts.build
@feed_items = current_user.feed.paginate(page: params[:page])
# feedの内容はMicropostなので、上のcurrent_user.microposts.と実質は変わらない(?
# このfeedをTopページのrenderingで使って、タイムラインを作る
end
end
投稿失敗時のErrorはよく分からなかった
destroyアクション
destroyアクションの内容は大丈夫だが、delete権限のある人を投稿した人に限定する実装は理解した自信がない
def correct_user
@micropost = current_user.microposts.find_by(id: params[:id])
# params[:id]には/micropostsにDELETEリクエストを送った人のidが入っていて、
# そのidが現在ログインしている人のidと等しいかどうかチェックしている(?
redirect_to root_url if @micropost.nil?
end