残りの API を実装しよう - satococoa/api-tutorial GitHub Wiki
引き続き、API を実装していきます。 spec -> 実装の順で開発します。
spec を書く上では、次のページを参考にするとスムーズにいけると思います。
新規投稿機能
spec
こんな感じの spec を追加
describe "POST /api/v1/posts" do
let(:params) {
{post: post_param, format: :json}
}
context "正しいパラメータが送られたとき" do
let(:post_param) { FactoryGirl.attributes_for(:post) }
it "201 が返る" do
post api_v1_posts_path, params
expect(response.status).to eq(201)
end
it "1 つ投稿が増える" do
expect { post api_v1_posts_path, params }.to change { Post.count }.by(1)
end
end
context "不正なパラメータが送られたとき" do
let(:post_param) { FactoryGirl.attributes_for(:post, title: 'a') }
it "422 が返る" do
post api_v1_posts_path, params
expect(response.status).to eq(422)
end
it "投稿は増えない" do
expect { post api_v1_posts_path, params }.not_to change { Post.count }
end
it "エラーメッセージがbodyに含まれる" do
post api_v1_posts_path, params
expect(response.body).not_to be_empty
end
end
end
実装コード
def create
@post = Post.new(post_params)
if @post.save
render json: 'ok', status: :created
else
render json: @post.errors.full_messages, status: :unprocessable_entity
end
end
private
def post_params
params.require(:post).permit(:title, :name, :body)
end
respond_to
, respond_with
などを使って書くこともできますが、上記の書き方が何をしているのかわかりやすいので良いかと思います。
実際に json のリクエストを試してみるときは、Dev HTTP Client という chrome の拡張が便利です。
投稿の更新機能
spec
describe "PATCH /api/v1/posts/:id" do
let(:params) {
{post: post_param, format: :json}
}
let(:post) { FactoryGirl.create(:post) }
context "正しいパラメータが送られたとき" do
let(:post_param) { FactoryGirl.attributes_for(:post) }
it "201 が返る" do
patch api_v1_post_path(post), params
expect(response.status).to eq(201)
end
it "投稿が更新される" do
patch api_v1_post_path(post), params
expect(Post.find(post.id).title).to eq(post_param[:title])
end
end
context "不正なパラメータが送られたとき" do
let(:post_param) { FactoryGirl.attributes_for(:post, title: 'a') }
it "422 が返る" do
patch api_v1_post_path(post), params
expect(response.status).to eq(422)
end
it "投稿が更新されない" do
patch api_v1_post_path(post), params
expect(Post.find(post.id).title).to eq(post.title)
end
it "エラーメッセージがbodyに含まれる" do
patch api_v1_post_path(post), params
expect(response.body).not_to be_empty
end
end
end
実装コード
def update
@post = Post.find(params[:id])
if @post.update(post_params)
render json: 'ok', status: :created
else
render json: @post.errors.full_messages, status: :unprocessable_entity
end
end
投稿の削除機能
spec
describe "DELETE /api/v1/posts/:id" do
let!(:post) { FactoryGirl.create(:post) }
it "200 が返る" do
delete api_v1_post_path(post)
expect(response.status).to eq(200)
end
it "1 つ投稿が減る" do
expect { delete api_v1_post_path(post) }.to change { Post.count }.by(-1)
end
end
実装コード
def destroy
@post = Post.find(params[:id])
@post.destroy
render json: 'ok', status: :ok
end