[RUBY] # 6 show, create implementation to build bulletin board API with authentication authorization in Rails 6

Building a bulletin board API with authentication authorization with Rails 6 # 5 controller, routes implementation

show test implementation

Continuing from the previous index, we will implement show testing and controller. show is the behavior of finding and returning based on the id of the parameter.

Is the test about returning a response normally and returning 404 when the ID does not exist?

spec/requests/v1/posts_controller.rb


...

+  describe "GET /v1/posts#show" do
+    let(:post) do
+      create(:post, subject: "show test")
+    end
+    it "Normal response code is returned" do
+      get v1_post_url({ id: post.id })
+      expect(response.status).to eq 200
+    end
+    it "subject is returned correctly" do
+      get v1_post_url({ id: post.id })
+      json = JSON.parse(response.body)
+      expect(json["post"]["subject"]).to eq("show test")
+    end
+    it "404 response is returned when id does not exist" do
+      get v1_post_url({ id: post.id + 1 })
+      expect(response.status).to eq 404
+    end
+  end
...

The explanation was missing, but let is lazily evaluated when called. In other words, it will not be executed until the variable post is called, but will be executed when it is called.

In the above example, it will be created when it is called post.id in the it block. Of course, the controller is not implemented, so the test is moss.

show implementation

app/controllers/v1/posts_controller.rb


...
     def show
-      # TODO
+      render json: { post: @post }
     end
...

Two of the three added tests will pass, but the remaining one will not pass the 404 error test. I'm getting a RecordNotFound exception in Rails and I'm getting a non-json response.

Modify application_controller.rb, which is a super class for all controllers.

app/controller/application_controller.rb


 # frozen_string_literal: true

 #
 #super class of controller
 #
 class ApplicationController < ActionController::API
+  rescue_from ActiveRecord::RecordNotFound, with: :render_404


+  def render_404
+    render status: 404, json: { message: "record not found." }
+   end
 end

By responding as above, when a record not found (ActiveRecord :: RecordNotFound) exception is thrown, it will be rescued and render_404 will be executed. And as status: 404, json is returned with a 404 response code.

If implemented so far, the test will pass. Just in case, let's check it with curl.

$ curl localhost:8080/v1/posts/0
{"message":"record not found."}
$ curl localhost:8080/v1/posts/1
{"post":{"id":1,"subject":"hoge","body":"fuga","created_at":"2020-09-05T13:50:01.797Z","updated_at":"2020-09-05T13:50:01.797Z"}}

create test implementation

Since create creates a new record, make sure that it increases by one record, that the added record matches the time of registration, and that it cannot be created when the parameter is incorrect.

spec/requests/v1/posts_controller.rb


+  describe "POST /v1/posts#create" do
+    let(:new_post) do
+      attributes_for(:post, subject: "create_subject test", body: "create_body test")
+    end
+    it "Normal response code is returned" do
+      post v1_posts_url, params: new_post
+      expect(response.status).to eq 200
+    end
+    it "One more case will be returned" do
+      expect do
+        post v1_posts_url, params: new_post
+      end.to change { Post.count }.by(1)
+    end
+    it "subject,body returns correctly" do
+      post v1_posts_url, params: new_post
+      json = JSON.parse(response.body)
+      expect(json["post"]["subject"]).to eq("create_subject test")
+      expect(json["post"]["body"]).to eq("create_body test")
+    end
+    it "Errors are returned when the parameter is invalid" do
+      post v1_posts_url, params: {}
+      json = JSON.parse(response.body)
+      expect(json.key?("errors")).to be true
+    end
+  end

If you use ʻattributes_for`, the object will be returned without saving to the DB like build. At that time, it is returned as a simple object instead of ActiveRecord format, and it is convenient because there are no unnecessary columns at the time of post such as id, created_at, updated_at.

At this time, please be careful not to change the variable name to post. At the time of writing the article, I made it post, and it became post v1_posts_url, params: post, and the post of get and post was overridden and the test did not work properly ... It took a long time to resolve: sweat_smile:

expect do post v1_posts_url, params: new_post end.to change { Post.count }.by(1) This block is a test in which Post.count is incremented by 1 by posting. The point is that expect is a block instead of ʻexpect.to eq`.

implementation of create

Implement controller.

app/controllers/v1/posts_controller.rb


...

     def create
-      # TODO
+      post = Post.new(post_params)
+      if post.save
+        render json: { post: post }
+      else
+        render json: { errors: post.errors }
+      end
    end
...
$ curl localhost:8080/v1/posts -X POST -H 'Content-Type: application/json' -d '{"subject":"moge","body":"hoge"}'        
{"post":{"id":3,"subject":"moge","body":"hoge","created_at":"2020-09-06T10:31:38.375Z","updated_at":"2020-09-06T10:31:38.375Z"}}

If rubocop and rspec work normally, commit.

I used it as a reference in this article. Thank you very much. Reference: Super easy API with Rails

Continued

Building a bulletin board API with authentication authorization in Rails 6 # 7 update, destroy implementation

[To the serial table of contents]

Recommended Posts

# 6 show, create implementation to build bulletin board API with authentication authorization in Rails 6
# 8 seed implementation to build bulletin board API with authentication authorization in Rails 6
# 7 update, destroy implementation to build bulletin board API with authentication authorization in Rails 6
# 16 policy setting to build bulletin board API with authentication authorization in Rails 6
Introduced # 9 serializer to build bulletin board API with authentication authorization in Rails 6
Build a bulletin board API with authentication authorization in Rails 6 # 5 controller, routes implementation
Introduced # 10 devise_token_auth to build a bulletin board API with authentication authorization in Rails 6
Introducing # 15 pundit to build a bulletin board API with authentication authorization in Rails 6
Build a bulletin board API with authentication authorization in Rails # 13 Add authentication header
Build a bulletin board API with authentication authorization in Rails # 17 Add administrator privileges
Build a bulletin board API with authentication authorization in Rails 6 # 14 seed Execution time display
Build a bulletin board API with authentication and authorization with Rails # 18 ・ Implementation of final user controller
Build a bulletin board API with authentication authorization in Rails # 12 Association of user and post
Build a bulletin board API with authentication and authorization with Rails 6 # 1 Environment construction
Build a bulletin board API with authentication authorization in Rails 6 # 11 User model test and validation added
Build a bulletin board API with authentication authorization with Rails 6 # 2 Introducing git and rubocop
Building a bulletin board API with authentication authorization with Rails 6 Validation and test implementation of # 4 post
Build a bulletin board API with authentication authorization with Rails 6 # 3 RSpec, FactoryBot introduced and post model
Try to create a bulletin board in Java
How to build API with GraphQL and Rails
[Rails] Create API to download files with Active Storage [S3]
[Implementation procedure] Create a user authentication function using sorcery in Rails
I implemented Rails API with TDD by RSpec. part3-Action implementation with authentication-
I tried to make a group function (bulletin board) with Rails
I implemented Rails API with TDD by RSpec. part1-Action implementation without authentication-
Create a SPA with authentication function with Rails API mode + devise_token_auth + Vue.js 3 (Rails edition)
How to build Rails 6 environment with Docker
Create authentication function in Rails application using devise
Create a simple bulletin board with Java + MySQL
[Rails] rails new to create a database with PostgreSQL
One way to redirect_to with parameters in rails
How to easily create a pull-down in Rails
[Rails] How to build an environment with Docker
Docker command to create Rails project with a single blow in environment without Ruby
[How to insert a video in haml with Rails]
Using PAY.JP API with Rails ~ Implementation Preparation ~ (payjp.js v2)
How to query Array in jsonb with Rails + postgres
Build Rails (API) x MySQL x Nuxt.js environment with Docker
Create API key authentication for Web API in Spring Security
A new employee tried to create an authentication / authorization function from scratch with Spring Security
Tutorial to create a blog with Rails for beginners Part 1
[Rails] I tried to create a mini app with FullCalendar
Implementation policy to dynamically save and display Timezone in Rails
Create a SlackBot with AWS lambda & API Gateway in Java
A series of steps to create portfolio deliverables with Rails
Create API to send and receive Json data in Spring
[Apple login] Sign in with Apple implementation procedure (Ruby on Rails)
How to build Rails, Postgres, ElasticSearch development environment with Docker
Tutorial to create a blog with Rails for beginners Part 2
How to set up a proxy with authentication in Feign
Things to keep in mind when using Sidekiq with Rails
Tutorial to create a blog with Rails for beginners Part 0
I tried to create an API to get data from a spreadsheet in Ruby (with service account)