- create rails project
- postgresql docker
- CURL
- apache bench mark
- testing
- rspec
- paging
- Allow anything through CORS Policy
- error
- api only
- rails version 5.1.6 (knock not working in 5.2)
- postgresql
rails _5.1.6_ new sample-api2 --api --database=postgresql -T
vi ~/.profile
POSTGRES_USER="postgres"
POSTGRES_DB="postgres"
POSTGRES_CONTAINER_NAME="postgres"
POSTGRES_PASSWORD=""
source ~/.profile
or
echo 'POSTGRES_USER="postgres"
POSTGRES_DB="postgres"
POSTGRES_CONTAINER_NAME="postgres"
POSTGRES_PASSWORD=""
'>> ~/.profile
source ~/.profile
docker \
run \
--volume ~/postgres:/var/lib/postgresql/data \
--env POSTGRES_USER=${POSTGRES_USER} \
--env POSTGRES_DB=${POSTGRES_DB} \
--env POSTGRES_PASSWORD=${POSTGRES_PASSWORD} \
--name ${POSTGRES_CONTAINER_NAME} \
--publish 5433:5432 \
postgres:9.6.10;
gem update --system
xcode-select --install # Then agree to the terms, even if you have done this before!
brew install postgresql
bundle install
https://medium.com/@nick.hartunian/knock-jwt-auth-for-rails-api-create-react-app-6765192e295a
default: &default
adapter: postgresql
encoding: unicode
host: localhost
port: 5433
username: postgres
password:
# For details on connection pooling, see Rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
development:
<<: *default
database: sample-api3_development
admin = User.new
admin.email = '[email protected]'
admin.password = 'bananaKing'
admin.password_confirmation = 'bananaKing'
admin.admin = true
admin.save
user = User.new
user.email = '[email protected]'
user.password = 'bananaBro'
user.password_confirmation = 'bananaBro'
user.save
gem 'knock'
$ bundle install
$ rails generate knock:install
rake db:create
rake db:migrate
rails generate knock:token_controller user
rails g scaffold user email password_digest admin:boolean
class User < ActiveRecord::Base
has_secure_password
end
class ApplicationController < ActionController::API
include Knock::Authenticable
def is_owner user_id
unless user_id == current_user.id
render json: nil, status: 403
return
end
end
end
rails g scaffold Post title:string body:text
rake db:migrate
rake db:seed
rails generate migration AddUserRefToPosts user:references
rake db:migrate
class PostsController < ApplicationController
before_action :authenticate_user
Rails.application.routes.draw do
scope '/api' do
resources :posts
resources :users
post 'user_token' => 'user_token#create'
end
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
https://scotch.io/tutorials/build-a-restful-json-api-with-rails-5-part-three
def destroy
if @post.user_id == current_user.id
@post.destroy
else
render json: nil, status: 403
end
end
or
class PostsController < ApplicationController
before_action :authenticate_user
before_action :set_post, only: [:show, :update, :destroy]
before_action only: [:update, :destroy] do
is_owner @post.user_id
end
def post_params
params.require(:post).permit(:title, :body).merge(user_id: current_user.id)
end
curl -X POST -i http://localhost:3000/api/v1/user_token -H "Content-Type: application/json" -d '{"auth":{"email":"[email protected]","password":"bananaKing"}}'
curl -X POST -i http://localhost:3000/api/v1/posts -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzgzMzE2NDUsInN1YiI6MX0.dldfr3gqSfS1KlfmrJakiDFIj2qcY1l2jP2unxGu81w" \
-d '{"post":{"title":"hello3","body":"hell"}}'
curl -X GET -i http://localhost:3000/api/v1/posts -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzgzMzE2NDUsInN1YiI6MX0.dldfr3gqSfS1KlfmrJakiDFIj2qcY1l2jP2unxGu81w" | jq
curl -X POST -i http://localhost:3000/api/v1/user_token -H "Content-Type: application/json" -d '{"auth":{"email":"[email protected]","password":"bananaBro"}}'
curl -X POST -i http://localhost:3000/api/v1/posts -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzc4OTA4NzMsInN1YiI6Mn0.xvHvrFWjK7jV-YE4Q05YzrENqHwFeFPAvwOUSV2b0kc" \
-d '{"title":"hello3","body":"hell"}'
curl -X DELETE -i http://localhost:3000/api/v1/posts/1 -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzc4OTA4NzMsInN1YiI6Mn0.xvHvrFWjK7jV-YE4Q05YzrENqHwFeFPAvwOUSV2b0kc"
curl -X DELETE -i http://localhost:3000/api/v1/posts/6 -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzc4OTA4NzMsInN1YiI6Mn0.xvHvrFWjK7jV-YE4Q05YzrENqHwFeFPAvwOUSV2b0kc"
curl -X POST -i http://localhost:3000/api/v1/posts -H "Content-Type: application/json"
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzc4OTA4NzMsInN1YiI6Mn0.xvHvrFWjK7jV-YE4Q05YzrENqHwFeFPAvwOUSV2b0kc"
-d '{"title":"hello123","body":"hell"}'
#!/bin/bash
for i in {1..100000}
do
echo -e "\nWelcome $i times \n"
curl -X POST -i http://localhost:3000/api/v1/posts -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzc4OTA4NzMsInN1YiI6Mn0.xvHvrFWjK7jV-YE4Q05YzrENqHwFeFPAvwOUSV2b0kc" \
-d '{"title":"hello '$i'","body":"hell"}'
done
curl -X POST -i http://localhost:3000/api/v1/posts -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzc4OTA4NzMsInN1YiI6Mn0.xvHvrFWjK7jV-YE4Q05YzrENqHwFeFPAvwOUSV2b0kc" \
-d '{"title":"hello123","body":"hell"}'
curl -X DELETE -i http://localhost:3000/api/v1/posts/10256 -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzc4OTA4NzMsInN1YiI6Mn0.xvHvrFWjK7jV-YE4Q05YzrENqHwFeFPAvwOUSV2b0kc"
curl -X DELETE -i http://localhost:3000/api/v1/posts/10256 -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MzgzMzE2NDUsInN1YiI6MX0.dldfr3gqSfS1KlfmrJakiDFIj2qcY1l2jP2unxGu81w"
- post json parameter request
- https://gist.github.com/kelvinn/6a1c51b8976acf25bd78
echo "{\"title\":\"hello123\",\"body\":\"hell\"}" > post_loc.txt
$ ab -p post_loc.txt -T application/json \
-H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzc4OTA4NzMsInN1YiI6Mn0.xvHvrFWjK7jV-YE4Q05YzrENqHwFeFPAvwOUSV2b0kc' \
-c 100 -n 100000 http://127.0.0.1:3000/api/v1/posts
This is ApacheBench, Version 2.3 <$Revision: 1826891 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software:
Server Hostname: 127.0.0.1
Server Port: 3000
Document Path: /api/v1/posts
Document Length: 159 bytes
Concurrency Level: 100
Time taken for tests: 573.782 seconds
Complete requests: 100000
Failed requests: 32258
(Connect: 0, Receive: 0, Length: 32258, Exceptions: 0)
Total transferred: 44864516 bytes
Total body sent: 34100000
HTML transferred: 15932258 bytes
Requests per second: 174.28 [#/sec] (mean)
Time per request: 573.782 [ms] (mean)
Time per request: 5.738 [ms] (mean, across all concurrent requests)
Transfer rate: 76.36 [Kbytes/sec] received
58.04 kb/s sent
134.40 kb/s total
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 30
Processing: 14 573 104.9 554 1678
Waiting: 8 572 104.9 553 1678
Total: 14 573 104.9 554 1678
Percentage of the requests served within a certain time (ms)
50% 554
66% 566
75% 575
80% 583
90% 609
95% 659
98% 813
99% 1254
100% 1678 (longest request)
brew install jq
curl -X GET http://localhost:3000/api/v1/posts -H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1Mzc4OTA4NzMsInN1YiI6Mn0.xvHvrFWjK7jV-YE4Q05YzrENqHwFeFPAvwOUSV2b0kc" | jq
rails test
or
rails test test/controllers/posts_controller_test.rb
or
rails test test/controllers/users_controller_test.rb
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
title: MyString
body: MyText
user_id: 1
two:
title: MyString
body: MyText
user_id: 2
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
id: 1
email: aaaa@aa.com
password_digest: <%= BCrypt::Password.create('secret', cost: 4) %>
admin: false
two:
id: 2
email: string@aa.com
password_digest: <%= BCrypt::Password.create('secret', cost: 4) %>
admin: false
require 'test_helper'
class PostsControllerTest < ActionDispatch::IntegrationTest
setup do
@post = posts(:one)
end
def authenticated_header
token = Knock::AuthToken.new(payload: { sub: users(:one).id }).token
{
'Authorization': "Bearer #{token}"
}
end
test "should get index" do
get posts_url, as: :json, headers: authenticated_header
assert_response :success
end
test "should create post" do
assert_difference('Post.count') do
post posts_url, params: { post: { body: @post.body, title: @post.title } }, as: :json, headers: authenticated_header
end
assert_response 201
end
test "should show post" do
get post_url(@post), as: :json, headers: authenticated_header
assert_response :success
end
test "should update post" do
patch post_url(@post), params: { post: { body: @post.body, title: @post.title } }, as: :json, headers: authenticated_header
assert_response 200
end
test "should destroy post" do
assert_difference('Post.count', -1) do
delete post_url(@post), as: :json, headers: authenticated_header
end
assert_response 204
end
end
require 'test_helper'
class UsersControllerTest < ActionDispatch::IntegrationTest
setup do
@user = users(:one)
end
test "should create user_token" do
post user_token_url, params: { auth: { email: @user.email, password:'secret' } }, as: :json
assert_response 201
end
end
https://www.rubydoc.info/gems/factory_bot/file/GETTING_STARTED.md https://tenderlovemaking.com/2015/01/23/my-experience-with-minitest-and-rspec.html https://github.com/rspec/rspec-rails https://relishapp.com/rspec/rspec-rails/docs/generators https://scotch.io/tutorials/build-a-restful-json-api-with-rails-5-part-one
group :development, :test do
gem 'rspec-rails', '~> 3.8'
end
group :test do
gem 'factory_bot_rails', '~> 4.0'
gem 'faker'
gem 'database_cleaner'
end
$ bundle install
$ rails generate rspec:install
Running via Spring preloader in process 25843
create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
$ rails generate rspec:scaffold post
Running via Spring preloader in process 25895
create spec/controllers/posts_controller_spec.rb
create spec/routing/posts_routing_spec.rb
invoke rspec
create spec/requests/posts_spec.rb
$ rails generate rspec:model post
mkdir spec/requests && touch spec/requests/{posts_spec.rb,users_spec.rb}
require 'rails_helper'
RSpec.describe "Posts", type: :request do
let(:user) { create(:user) }
let(:headers) { authenticated_header(user.id) }
describe "GET #index" do
it "returns a success response" do
get posts_path, params: {}, headers: headers
expect(response).to be_successful
end
end
end
mkdir spec/factories
touch spec/factories/{posts.rb,users.rb}
FactoryBot.define do
factory :post do
title { Faker::Lorem.word }
body { Faker::Lorem.word }
user_id { Faker::Number.number(1) }
end
end
FactoryBot.define do
factory :user do
email { '[email protected]' }
password_digest { BCrypt::Password.create('bananaBro', cost: 4) }
admin {false}
end
end
mkdir spec/support
touch spec/support/controller_spec_helper.rb
# spec/support/controller_spec_helper.rb
module ControllerSpecHelper
def authenticated_header user_id
token = Knock::AuthToken.new(payload: { sub: user_id }).token
{
'Authorization': "Bearer #{token}"
}
end
end
# add `FactoryBot` methods
config.include FactoryBot::Syntax::Methods
# require database cleaner at the top level
require 'database_cleaner'
RSpec.configure do |config|
# start by truncating all the tables but then use the faster transaction strategy the rest of the time.
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
DatabaseCleaner.strategy = :transaction
end
# start the transaction strategy as examples are run
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
config.include ControllerSpecHelper
$ bundle exec rspec ./spec/controllers/posts_controller_spec.rb
https://relishapp.com/rspec/rspec-rails/docs/gettingstarted
$ bundle exec rspec spec/controllers/posts_controller_spec.rb --format documentation
PostsController
GET #index
returns a success response
GET #show
returns a success response
POST #create
with valid params
creates a new Post
renders a JSON response with the new post
with invalid params
renders a JSON response with errors for the new post
PUT #update
with valid params
updates the requested post (PENDING: Add a hash of attributes valid for your model)
renders a JSON response with the post
with invalid params
renders a JSON response with errors for the post
DELETE #destroy
destroys the requested post
Pending: (Failures listed here are expected and do not affect your suite's status)
1) PostsController PUT #update with valid params updates the requested post
# Add a hash of attributes valid for your model
# ./spec/controllers/posts_controller_spec.rb:106
Finished in 1.22 seconds (files took 1.85 seconds to load)
9 examples, 0 failures, 1 pending
require 'rails_helper'
# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec. Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.
#
# Also compared to earlier versions of this generator, there are no longer any
# expectations of assigns and templates rendered. These features have been
# removed from Rails core in Rails 5, but can be added back in via the
# `rails-controller-testing` gem.
RSpec.describe PostsController, type: :controller do
# This should return the minimal set of attributes required to create a valid
# Post. As you add validations to Post, be sure to
# adjust the attributes here as well.
let(:valid_attributes) {
{
title: Faker::Lorem.word,
body: Faker::Lorem.word,
user_id: user.id
}
}
let(:invalid_attributes) {
{
title: "",
body: ""
}
}
let(:user) { create(:user) }
# let(:user) { create(:user) }
# let(:valid_attributes) { create(:post, :user_id => user.id).attributes }
let(:posts) { create_list(:post, 10) }
let(:headers) { authenticated_header(user.id) }
describe "GET #index" do
it "returns a success response" do
puts "hello world #{valid_attributes} "
# puts "hello world #{valid_attributes.attributes} "
# puts "user #{user.attributes} "
# puts "user2 #{valid_attributes.user_id} "
post = Post.create! valid_attributes
request.headers.merge! headers
get :index, params: {}
expect(response).to be_successful
end
end
describe "GET #show" do
it "returns a success response" do
post = Post.create! valid_attributes
request.headers.merge! headers
get :show, params: {id: post.to_param}
expect(response).to be_successful
end
end
describe "POST #create" do
context "with valid params" do
it "creates a new Post" do
expect {
request.headers.merge! headers
post :create, params: {post: valid_attributes}
}.to change(Post, :count).by(1)
end
it "renders a JSON response with the new post" do
request.headers.merge! headers
post :create, params: {post: valid_attributes}
expect(response).to have_http_status(:created)
expect(response.content_type).to eq('application/json')
expect(response.location).to eq(post_url(Post.last))
end
end
context "with invalid params" do
it "renders a JSON response with errors for the new post" do
request.headers.merge! headers
post :create, params: {post: invalid_attributes}
expect(response).to have_http_status(:unprocessable_entity)
expect(response.content_type).to eq('application/json')
end
end
context "with invalid authenticate" do
it "renders a JSON response with errors for the new post" do
post :create, params: {post: valid_attributes}
expect(response).to have_http_status(:unauthorized)
end
end
end
describe "PUT #update" do
context "with valid params" do
let(:new_attributes) {
{
title: "update",
body: "welcome to hell o"
}
}
it "updates the requested post" do
post = Post.create! valid_attributes
request.headers.merge! headers
put :update, params: {id: post.to_param, post: new_attributes}
post.reload
end
it "renders a JSON response with the post" do
post = Post.create! valid_attributes
request.headers.merge! headers
put :update, params: {id: post.to_param, post: valid_attributes}
expect(response).to have_http_status(:ok)
expect(response.content_type).to eq('application/json')
end
end
context "with invalid params" do
it "renders a JSON response with errors for the post" do
post = Post.create! valid_attributes
request.headers.merge! headers
put :update, params: {id: post.to_param, post: invalid_attributes}
expect(response).to have_http_status(:unprocessable_entity)
expect(response.content_type).to eq('application/json')
end
end
end
describe "DELETE #destroy" do
it "destroys the requested post" do
post = Post.create! valid_attributes
expect {
request.headers.merge! headers
delete :destroy, params: {id: post.to_param}
}.to change(Post, :count).by(-1)
end
end
end
require 'rails_helper'
RSpec.describe "Posts", type: :request do
describe "GET /posts" do
it "works! (now write some real specs)" do
get posts_path
expect(response).to have_http_status(:unauthorized)
end
end
end
require "rails_helper"
RSpec.describe PostsController, type: :routing do
describe "routing" do
it "routes to #index" do
expect(:get => "/api/v1/posts").to route_to("posts#index")
end
it "routes to #show" do
expect(:get => "/api/v1/posts/1").to route_to("posts#show", :id => "1")
end
it "routes to #create" do
expect(:post => "/api/v1/posts").to route_to("posts#create")
end
it "routes to #update via PUT" do
expect(:put => "/api/v1/posts/1").to route_to("posts#update", :id => "1")
end
it "routes to #update via PATCH" do
expect(:patch => "/api/v1/posts/1").to route_to("posts#update", :id => "1")
end
it "routes to #destroy" do
expect(:delete => "/api/v1/posts/1").to route_to("posts#destroy", :id => "1")
end
end
end
$ bundle exec rspec
hello world {:title=>"sint", :body=>"quibusdam", :user_id=>41}
.................
Finished in 0.93529 seconds (files took 1.62 seconds to load)
17 examples, 0 failures
$ bundle exec rspec --format documentation
PostsController
GET #index
hello world {:title=>"repellendus", :body=>"aperiam", :user_id=>51}
returns a success response
GET #show
returns a success response
POST #create
with valid params
creates a new Post
renders a JSON response with the new post
with invalid params
renders a JSON response with errors for the new post
with invalid authenticate
renders a JSON response with errors for the new post
PUT #update
with valid params
updates the requested post
renders a JSON response with the post
with invalid params
renders a JSON response with errors for the post
DELETE #destroy
destroys the requested post
Posts
GET /posts
works! (now write some real specs)
PostsController
routing
routes to #index
routes to #show
routes to #create
routes to #update via PUT
routes to #update via PATCH
routes to #destroy
Finished in 0.96735 seconds (files took 1.61 seconds to load)
17 examples, 0 failures
$ rails generate rspec:scaffold user
Running via Spring preloader in process 91026
create spec/controllers/users_controller_spec.rb
create spec/routing/users_routing_spec.rb
invoke rspec
create spec/requests/users_spec.rb
require 'rails_helper'
# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec. Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.
#
# Also compared to earlier versions of this generator, there are no longer any
# expectations of assigns and templates rendered. These features have been
# removed from Rails core in Rails 5, but can be added back in via the
# `rails-controller-testing` gem.
RSpec.describe UsersController, type: :controller do
# This should return the minimal set of attributes required to create a valid
# User. As you add validations to User, be sure to
# adjust the attributes here as well.
let(:valid_attributes) {
{
email: Faker::Internet.email,
password_digest: BCrypt::Password.create(Faker::Internet.password, cost: 4),
admin: false
}
}
let(:invalid_attributes) {
{
email: "",
password_digest: nil,
admin: false
}
}
let(:user) { create(:user) }
describe "GET #index" do
it "returns a success response" do
user = User.create! valid_attributes
get :index, params: {}
expect(response).to be_successful
end
end
describe "GET #show" do
it "returns a success response" do
user = User.create! valid_attributes
request.headers.merge! authenticated_header(user.id)
get :show, params: {id: user.to_param}
expect(response).to be_successful
end
end
describe "POST #create" do
context "with valid params" do
it "creates a new User" do
expect {
post :create, params: {user: valid_attributes}
}.to change(User, :count).by(1)
end
it "renders a JSON response with the new user" do
post :create, params: {user: valid_attributes}
expect(response).to have_http_status(:created)
expect(response.content_type).to eq('application/json')
expect(response.location).to eq(user_url(User.last))
end
end
context "with invalid params" do
it "renders a JSON response with errors for the new user" do
post :create, params: {user: invalid_attributes}
expect(response).to have_http_status(:unprocessable_entity)
expect(response.content_type).to eq('application/json')
end
end
end
describe "PUT #update" do
context "with valid params" do
let(:new_attributes) {
{
email: Faker::Internet.email,
password_digest: BCrypt::Password.create(Faker::Internet.password, cost: 4),
admin: true
}
}
it "updates the requested user" do
user = User.create! valid_attributes
request.headers.merge! authenticated_header(user.id)
put :update, params: {id: user.to_param, user: new_attributes}
user.reload
expect(response).to have_http_status(:ok)
expect(response.content_type).to eq('application/json')
expect(user.email).to eq(new_attributes[:email])
expect(user.password_digest).to eq(new_attributes[:password_digest])
expect(user.admin).to eq(new_attributes[:admin])
end
it "renders a JSON response with the user" do
user = User.create! valid_attributes
request.headers.merge! authenticated_header(user.id)
put :update, params: {id: user.to_param, user: valid_attributes}
expect(response).to have_http_status(:ok)
expect(response.content_type).to eq('application/json')
end
end
context "with invalid params" do
it "renders a JSON response with errors for the user" do
user = User.create! valid_attributes
request.headers.merge! authenticated_header(user.id)
put :update, params: {id: user.to_param, user: invalid_attributes}
expect(response).to have_http_status(:unprocessable_entity)
expect(response.content_type).to eq('application/json')
end
end
end
describe "DELETE #destroy" do
it "destroys the requested user" do
user = User.create! valid_attributes
expect {
request.headers.merge! authenticated_header(user.id)
delete :destroy, params: {id: user.to_param}
}.to change(User, :count).by(-1)
end
end
end
class PostsController < ApplicationController
before_action :authenticate_user
before_action :set_post, only: [:show, :update, :destroy]
before_action only: [:update, :destroy] do
is_owner @post.user_id
end
# GET /posts
def index
@posts = Post.paginate(page: params[:page], per_page: 20).order('id DESC')
render json: @posts
end
class Post < ApplicationRecord
# validations
validates_presence_of :title, :body
self.per_page = 20
end
#### Gemfile
```ruby
gem 'will_paginate', '~> 3.1.0'
- https://stackoverflow.com/questions/17858178/allow-anything-through-cors-policy
- https://github.com/cyu/rack-cors Gemfile
gem 'rack-cors', require: 'rack/cors'
config/application.rb
config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :options]
end
end