我正在尝试为产品模型执行租户执行。但在请求更新规范中,它显示以下错误: 期望响应具有状态代码:unprocessable_entity(422)但它是:forbidden(403)。
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :update, :destroy]
before_action :validate_tenant, only: [:show, :update, :destroy]
def index
@products=Product.where(tenant_id: current_context.tenant_id).all
render json: @products
end
def show
render json:@product
end
def create
@product= Product.create(product_params)
if @product.save
render json:@product, status: :created
else
render json: @product.errors, status: :unprocessable_entity
end
end
def update
if @product.update(product_params)
render json: @product
else
render json: @product.errors, status: :unprocessable_entity
end
end
def destroy
@product.destroy
end
private
def set_product
@product = Product.find(params[:id])
end
def validate_tenant
if @product and !@product.tenant_id.eql?(current_context.tenant_id)
raise ApiM8::Exceptions::TenantMismatch.new
end
if @product and product_params.include?(:tenant_id) and !@product.tenant_id.eql?(product_params[:tenant_id])
raise ApiM8::Exceptions::TenantMismatch.new
end
end
def product_params
json_api_params(Product,[:visible, :type, :tenant_id]).fetch(:attributes,{})
end
end
require 'rails_helper'
RSpec.describe ProductsController, :type => :controller do
before {
controller_stub_token_authentication
}
let(:valid_session) { {} }
let(:context) {
OpenStruct.new(
tenant_id: SecureRandom.uuid
)
}
before {
allow(controller).to receive(:current_context).and_return(context)
}
describe "GET index" do
let!(:products){ create_list :product, rand(2..10), tenant_id: context.tenant_id }
it "assigns all products as @products" do
get :index, parrams:{}, session:valid_session
expect(assigns(:products)).to eq(products)
end
end
describe "GET show" do
let!(:product) { create :product ,tenant_id: context.tenant_id }
it "assigns the requested product as @product" do
get :show, params:{:id => product.to_param}, session:valid_session
expect(assigns(:product)).to eq(product)
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Product" do
expect {
post :create, params: json_api_params(Product, attributes_for(:product)), session:valid_session
}.to change(Product, :count).by(1)
end
it "assigns a newly created product as @product" do
post :create,params: json_api_params(Product, attributes_for(:product)), session:valid_session
expect(assigns(:product)).to be_a(Product)
expect(assigns(:product)).to be_persisted
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved product as @product" do
post :create, params: json_api_params(Product, attributes_for(:product).update(tenant_id: nil)),session: valid_session
expect(assigns(:product)).to be_a_new(Product)
end
end
end
describe "PUT update" do
let!(:product) { create :product, tenant_id: context.tenant_id}
let(:new_attributes) {
attributes_for(:product).update(tenant_id: context.tenant_id)
}
describe "with valid params" do
it "updates the requested product" do
put :update,params: {:id => product.to_param}.update(json_api_params(Product,new_attributes)), session:valid_session
product.reload
new_attributes.each do |attr, val|
expect(product.send(attr)).to eq(val)
end
end
it "assigns the requested product as @product" do
put :update,params: {:id => product.to_param}.update(json_api_params(Product,new_attributes)), session:valid_session
expect(assigns(:product)).to eq(product)
end
end
describe "with invalid params" do
it "assigns the product as @product" do
put :update,params: {:id => product.to_param}.update(
json_api_params(Product,new_attributes.update(tenant_id: nil))),session: valid_session
expect(assigns(:product)).to eq(product)
end
end
end
describe "DELETE destroy" do
let!(:product){ create :product,tenant_id: context.tenant_id }
it "destroys the requested product" do
expect {
delete :destroy,params: {:id => product.to_param}, session:valid_session
}.to change(Product, :count).by(-1)
end
end
end
require 'rails_helper'
RSpec.describe "Products", :type => :request do
before {
controller_instance_stub_token_authentication(ProductsController)
}
let(:headers) {
{}.merge(token_authentication).merge(json_api_headers)
}
let(:context) {
OpenStruct.new(
tenant_id: SecureRandom.uuid
)
}
before {
allow_any_instance_of(ProductsController).to receive(:current_context).and_return(context)
}
describe 'GET /products' do
let!(:products) { create_list :product, rand(5..10),tenant_id: context.tenant_id }
it 'responds with :ok' do
get products_path, headers: headers, as: :json
expect(response).to have_http_status(:ok)
end
it 'responds with a list' do
get products_path, headers: headers, as: :json
expect(json_api_response).to be_a(Array)
end
it 'responds with a correct list' do
get products_path, headers: headers, as: :json
expect(json_api_response.size).to eq(products.count)
expect(products.map(&:id)).to include(json_api_response.first['id'])
expect(json_api_response.first['attributes']).to include('visible', 'url')
end
end
describe 'GET /products/:id' do
let!(:product) { create :product, tenant_id: context.tenant_id }
describe 'for existing item' do
it 'is a valid JSON API response' do
get product_path(product), headers: headers, as: :json
expect(response.body).to be_json_api_response_for(Product)
end
it 'responds with the correct item' do
get product_path(product), headers: headers, as: :json
expect(json_api_response['id']).to eq(product.id.to_s)
end
it 'responds with the correct information' do
get product_path(product), headers: headers, as: :json
expect(json_api_response['attributes']).to include('visible', 'url')
end
it 'responds with :ok' do
get product_path(product), headers: headers, as: :json
expect(response).to have_http_status(:ok)
end
end
describe 'for missing item' do
it 'responds with :not_found' do
get product_path(-1000), headers: headers, as: :json
expect(response).to have_http_status(:not_found)
end
end
end
describe 'POST /products' do
# let!(:product) { create :product, tenant_id: context.tenant_id}
describe 'with valid params' do
it 'responds with :created' do
_attrs = attributes_for(:product).slice(:visible, :tenant_id)
post products_path, params: json_api_params(Product, _attrs), headers: headers, as: :json
expect(response).to have_http_status(:created)
end
end
describe 'with invalid params' do
it 'responds with :unprocessable_entity' do
post products_path, params: json_api_params(Product, { tenant_id: nil }), headers: headers, as: :json
expect(response).to have_http_status(:unprocessable_entity)
end
end
end
describe 'PUT /products/:id' do
let!(:product) { create :product, tenant_id: context.tenant_id}
let(:new_attributes) { {tenant_id: context.tenant_id} }
#let(:new_attributes) { attributes_for(:product).update(tenant_id: context.tenant_id)}
describe 'with valid params' do
it 'updates the requested product' do
put product_path(product), params: json_api_params(Product, new_attributes), headers: headers, as: :json
product.reload
expect(product.attributes.with_indifferent_access).to include(new_attributes)
end
it 'responds with :ok' do
put product_path(product), params: json_api_params(Product, new_attributes), headers: headers, as: :json
expect(response).to have_http_status(:ok)
end
end
describe 'with invalid params' do
it 'responds with :unprocessable_entity' do
#skip('no fields to check this spec, :tenant is validated before AR::update')
put product_path(product), params: json_api_params(Product, { tenant_id:nil }), headers: headers, as: :json
expect(response).to have_http_status(:unprocessable_entity)
end
it 'responds with :forbidden for different :tenant' do
put product_path(product), params: json_api_params(Product, { tenant_id: SecureRandom.uuid }), headers: headers, as: :json
expect(response).to have_http_status(:forbidden)
end
end
describe 'with missing item' do
it 'responds with :not_found' do
put product_path(-1000), params: json_api_params(Product, new_attributes), headers: headers, as: :json
expect(response).to have_http_status(:not_found)
end
end
end
describe 'DELETE /products/:id' do
let!(:product) { create :product, tenant_id: context.tenant_id }
it 'for existing item, responds with :no_content' do
delete product_path(product), headers: headers, as: :json
expect(response).to have_http_status(:no_content)
end
it 'for missing item, responds with :not_found' do
delete product_path(-1000), headers: headers, as: :json
expect(response).to have_http_status(:not_found)
end
context 'responds with :forbidden' do
it 'for different :tenant' do
product.update(tenant_id: SecureRandom.uuid)
delete product_path(product), headers: headers, as: :json
expect(response).to have_http_status(:forbidden)
end
end
end
end