我使用this tutorial为我的Rails 5应用生成API。 这是在Comments和Post表之间。 帖子与评论的关系为1:m。
但是rspec每次测试都失败了。我一遍又一遍地检查了我的文件和层次结构,仍然没有看到问题所在。
以下是//JSON response
[{
"data": [{
"Title": "asde",
"abc": "asd23e",
"Material": "asdf",
"Quantity Jan2016 - Dec2016": 12576,
"Sales Jan2016 - Dec2016": 1
}, {
"Title": "asde",
"abc": "345fs",
"Material": "dsfvd 3343",
"Quantity Jan2016 - Dec2016": 16560,
"Sales Jan2016 - Dec2016": 6
}, {
"Title": "asde",
"abc": "7687",
"Material": "af asdf",
"Quantity Jan2016 - Dec2016": 12216,
"Sales Jan2016 - Dec2016": 1
}],
"totalPayloadSize": 539, // Total no. of entries
"pageFrom": 0, // 1st entry
"pageTo": 49, // 50th entry
"pageSize": 50, // no. of entries to be shown
"pageNo": 1, // 1st page, Pagination
"monthsIn": [{
"fMonth": 1,
"fYear": 2016,
"tMonth": 12,
"tYear": 2016
}]
}]
的输出:
rails routes
我的Prefix Verb URI Pattern Controller#Action
post_comments GET /posts/:post_id/comments(.:format) comments#index
POST /posts/:post_id/comments(.:format) comments#create
post_comment GET /posts/:post_id/comments/:id(.:format) comments#show
PATCH /posts/:post_id/comments/:id(.:format) comments#update
PUT /posts/:post_id/comments/:id(.:format) comments#update
DELETE /posts/:post_id/comments/:id(.:format) comments#destroy
post_like POST /posts/:post_id/like(.:format) posts#like
post_dislike POST /posts/:post_id/dislike(.:format) posts#dislike
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
post GET /posts/:id(.:format) posts#show
PATCH /posts/:id(.:format) posts#update
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
:
config/routes.rb
Rails.application.routes.draw do
resources :posts do
resources :comments
post :like
post :dislike
end
end
:(即使使用ActionController :: API,它也不起作用)
application_controller.rb
我的class ApplicationController < ActionController::Base
include Response
include ExceptionHandler
protect_from_forgery with: :exception
end
comments_controller.rb
最后,class CommentsController < ApplicationController
before_action :set_post
before_action :set_post_comment, only: [:show, :update, :destroy]
# GET /comments
# GET /comments.json
def index
#@comments = Comment.all
json_response(@post.comments)
end
# GET /comments/1
# GET /comments/1.json
def show
json_response(@comment)
end
# POST /comments
# POST /comments.json
def create
@comment = Comment.new(comment_params)
@post.comments.create!(comment_params)
json_response(@post, :created)
if @comment.save
render :show, status: :created, location: @comment
else
render json: @comment.errors, status: :unprocessable_entity
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
@comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:commenter, :comment, :description, :post)
end
def set_post
@post = Post.find(params[:post_id])
end
def set_post_comment
@comment = @post.comments.find_by!(id: params[:id]) if @post
end
end
:
posts_controller.rb
更新:显示规范文件
我的class PostsController < ApplicationController
before_action :set_post, only: [:show, :update, :destroy]
# GET /posts
# GET /posts.json
def index
@posts = Post.all
json_response(@posts)
end
# GET /posts/1
# GET /posts/1.json
def show
json_response(@post)
end
# POST /posts
# POST /posts.json
def create
@post = Post.new(post_params)
json_response(@post, :created)
if @post.save
render :show, status: :created, location: @post
else
render json: @post.errors, status: :unprocessable_entity
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
@post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:poster, :vote, :description, :comment, :user_id, :image_base)
end
end
:
spec/requests/comments_spec.rb
require 'rails_helper'
RSpec.describe "Comments", type: :request do
# Initialize the test data
let!(:post) { create(:post) }
let!(:comments) { create_list(:comment, 20, post_id: post.id) }
let(:post_id) { post.id }
let(:id) { comments.first.id }
# Test suite for GET /posts/:post_id/comments
describe 'GET /posts/:post_id/comments' do
before { get "/posts/#{post_id}/comments" }
context 'when post exists' do
it 'returns status code 200' do
expect(response).to have_http_status(200)
end
it 'returns all post comments' do
expect(json.size).to eq(20)
end
end
context 'when post does not exist' do
let(:post_id) { 0 }
it 'returns status code 404' do
expect(response).to have_http_status(404)
end
it 'returns a not found message' do
expect(response.body).to match(/Couldn't find Post/)
end
end
end
# Test suite for GET /posts/:post_id/comments/:id
describe 'GET /posts/:post_id/comments/:id' do
before { get "/posts/#{post_id}/comments/#{id}" }
context 'when post item exists' do
it 'returns status code 200' do
expect(response).to have_http_status(200)
end
it 'returns the item' do
expect(json['id']).to eq(id)
end
end
context 'when post item does not exist' do
let(:id) { 0 }
it 'returns status code 404' do
expect(response).to have_http_status(404)
end
it 'returns a not found message' do
expect(response.body).to match(/Couldn't find Comment/)
end
end
end
# Test suite for PUT /posts/:post_id/comments
describe 'POST /posts/:post_id/comments' do
let(:valid_attributes) { { comment: 'A Comment', commenter: 'Luke Shaw' } }
context 'when request attributes are valid' do
before { post "/posts/#{post_id}/comments", params: valid_attributes }
it 'returns status code 201' do
expect(response).to have_http_status(201)
end
end
context 'when an invalid request' do
before { post "/posts/#{post_id}/comments", params: {} }
it 'returns status code 422' do
expect(response).to have_http_status(422)
end
it 'returns a failure message' do
expect(response.body).to match(/Validation failed: Commenter or Comment can't be blank/)
end
end
end
end
:
spec/requests/posts_spec.rb
require 'rails_helper'
RSpec.describe "Posts", type: :request do
# initialize test data
let!(:posts) { create_list(:post, 10) }
let(:post_id) { posts.first.id }
describe "GET /posts" do
# make HTTP get request before each example
before { get '/posts' }
it 'returns posts' do
# Note `json` is a custom helper to parse JSON responses
expect(json).not_to be_empty
expect(json.size).to eq(10)
end
it 'returns status code 200' do
expect(response).to have_http_status(200)
end
end
# Test suite for GET /posts/:id
describe 'GET /posts/:id' do
before { get "/posts/#{post_id}" }
context 'when the record exists' do
it 'returns the post' do
expect(json).not_to be_empty
expect(json['id']).to eq(post_id)
end
it 'returns status code 200' do
expect(response).to have_http_status(200)
end
end
context 'when the record does not exist' do
let(:post_id) { 100 }
it 'returns status code 404' do
expect(response).to have_http_status(404)
end
it 'returns a not found message' do
expect(response.body).to match(/Couldn't find Post/)
end
end
end
:
spec/models/post_spec.rb
ANd require 'rails_helper'
RSpec.describe Post, type: :model do
# Association test
# ensure Post model has a 1:m relationship with the Comment model
it { should have_many(:comments).dependent(:destroy) }
# Validation tests
# ensure columns are present before saving
it { should validate_presence_of(:poster) }
it { should validate_presence_of(:description) }
end
:
spec/models/comment_spec.rb
更新2:显示spec / factories / * .rb文件
显示require 'rails_helper'
RSpec.describe Comment, type: :model do
# Association test
# ensure a comment record belongs to a single post record
it { should belong_to(:post) }
# Validation test
# ensure column name is present before saving
it { should validate_presence_of(:comment) }
it { should validate_presence_of(:commenter) }
end
:
spec/factories/posts.rb
显示FactoryBot.define do
factory :post do
image { Rack::Test::UploadedFile.new(Rails.root.join('public', 'system', 'posts', 'images', '000', '000', '001', 'original', 'img1.jpeg'), 'image/jpeg') }
poster { Faker::Lorem.sentence }
vote { Faker::Number.number(10).to_i}
description { Faker::Lorem.paragraph }
end
end
:
spec/factories/comments.rb
我的`路由显示明确的继承,我在我的控制器中强制执行。不过,我得到的错误如下:
失败/错误:期待(:delete =&gt;&#34; / comments / 1&#34;)。to route_to(&#34; comments#destroy&#34;,:id =&gt;&#34; 1&#34) 没有路线匹配&#34; / comments / 1&#34; 和 RuntimeError: /home/user/projects/app/public/system/posts/images/000/000/001/original/img1.jpeg文件不存在
答案 0 :(得分:1)
好的,导致每个规范失败的错误是上传的图像。它无法找到您尝试上传的图像文件。该图像文件实际位于何处?创建该文件并将其放在正确的位置,它们应该重新开始工作。
至于路由规范 - 这是您在问题中包含的错误,并且它只会根据您的粘贴垃圾箱本地化为您的路由规范(spec/routing/comments_routing_spec.rb
),只需将路线调整为嵌套路线即可修复。它们应该包括使路线工作所需的一切(包括有效的后id)。
其次,它应该是这样的:
expect(:delete => "/posts/1/comments/1").to route_to("comments#destroy", :id => "1", :post_id => "1")
注意:就我个人而言,我不会为简单资源而烦恼,只是为了复杂的资源,但是当你习惯使用Rails时,你可能更喜欢它作为备份。