復習のため、投稿機能を作成しようとしたところ、上記のエラーが出たので、解決方法をまとめます。
・ログイン後のユーザーが、投稿を行えるようにしたい
・sorceryを導入し、ユーザー登録機能は実装済み
・userとpostのデータの関係は、1対多である。
コードの内容
routes.rb
Rails.application.routes.draw do
root 'top#index'
get 'login', to: 'user_sessions#new'
post 'login', to: 'user_sessions#create'
delete 'logout', to: 'user_sessions#destroy'
resources :posts
resources :users
end
models/post.rb
class Post < ApplicationRecord
belongs_to :user, dependent: :destroy
validates :user_id, presence: true
validates :title, presence: true
validates :content, presence: true
end
models/user.rb
class User < ApplicationRecord
has_many :posts, dependent: :destroy
authenticates_with_sorcery!
validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] }
validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] }
validates :email, presence: true, uniqueness: true
end
views/posts/new.html.erb
<%= form_with model: @post,local: true do |f| %>
<p><%= f.label :title %><br>
<%= f.text_field :title %></p>
<p><%= f.label :content %><br>
<%= f.text_area :content %></p>
<%= f.submit "投稿する", class: "btn btn-primary" %>
<% end %>
解決方法
以下のようにcreateメソッドを修正したところ解決
app/controllers/posts_controller.rb
class PostsController < ApplicationController
def new
@post = Post.new
end
def create
@post = current_user.posts.build(post_params)
if @post.save
flash[:success] = "記事が作成できました。"
redirect_to @post
else
flash[:danger] = "記事の作成が失敗しました。もう一度試してください。"
render action: 'new'
end
end
private
def post_params
params.require(:post).permit(:title, :content)
end
end
@post = current_user.posts.build(post_params)の部分を、当初は@post = Post.new(post_params)としていた。
現在ログイン中のユーザーと投稿する本を紐づけるためには、sorceryのcurrent_userメソッドが必要(現在ログイン中のuserを返すメソッド)
また、モデルの関係性は、1対多の関係のため、postは複数形にする必要がある。
※補足
newメソッドとbuildメソッドは、インスタンスを生成するメソッドという点では共通しているので、buildをnewに変えても登録することが可能。しかし、モデルの関連付けの際にはbuildを使用する。
モデルを関連づけた際にはbuildメソッドを使用することが暗黙の了解。
参考