我是rails的新手,并且正在将关联嵌入到我的API模型中。但是添加嵌入导致我的规范引发以下错误: Rails:4.2.3 Ruby:2.2.1 Rspec:3.3.2 FactoryGirl:4.5.0
1) Api::V1::ProductsController GET #show returns the information about a reporter on a hash
Failure/Error: get :show, id: @product.id
SystemStackError:
stack level too deep
我认为从堆栈溢出的其他答案看,我在测试中如何使用我的工厂存在问题。
以下是型号: product.rb
class User < ActiveRecord::Base
validates :auth_token, uniqueness: true
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
before_create :generate_authentication_token!
has_many :products, dependent: :destroy
def generate_authentication_token!
begin
self.auth_token = Devise.friendly_token
end while self.class.exists?(auth_token: auth_token)
end
end
user.rb
class Product < ActiveRecord::Base
validates :title, :user_id, presence: true
validates :price, numericality: { greater_than_or_equal_to: 0 },
presence: true
belongs_to :user
end
和工厂: users.rb的
FactoryGirl.define do
factory :user do
email { FFaker::Internet.email }
password "12345678"
password_confirmation "12345678"
end
end
products.rb
FactoryGirl.define do
factory :product do
title { FFaker::Product.product_name }
price { rand() * 100 }
published false
user
end
end
这是我从中得到所有错误的规范。 products_controller_spec.rb
require 'spec_helper'
describe Api::V1::ProductsController do
describe "GET #show" do
before(:each) do
@product = FactoryGirl.create :product
get :show, id: @product.id
end
it "returns the information about a reporter on a hash" do
product_response = json_response[:product]
expect(product_response[:user][:email]).to eql @product.user.email
end
it "has the user as an embeded object" do
product_response = json_response[:product]
expect(product_response[:user][:email]).to eql @product.user.email
end
it { should respond_with 200 }
end
describe "GET #index" do
before(:each) do
4.times { FactoryGirl.create :product }
get :index
end
it "returns 4 records from the database" do
products_response = json_response
expect(products_response[:products]).to have(4).items
end
it "returns the user object into each product" do
products_response = json_response[:products]
products_response.each do |product_response|
expect(product_response[:user]).to be_present
end
end
it { should respond_with 200 }
end
describe "POST #create" do
context "when is succesfully created" do
before(:each) do
user = FactoryGirl.create :user
@product_attributes = FactoryGirl.attributes_for :product
api_authorization_header user.auth_token
post :create, { user_id: user.id, product: @product_attributes }
end
it "renders the json representation for the product record just created" do
product_response = json_response[:product]
expect(product_response[:title]).to eql @product_attributes[:title]
end
it { should respond_with 201 }
end
context "when is not created" do
before(:each) do
user = FactoryGirl.create :user
@invalid_product_attributes = { title: "Smart TV", price: "Twelve dolalrs" }
api_authorization_header user.auth_token
post :create, { user_id: user.id, product: @invalid_product_attributes }
end
it "renders an errors json" do
product_response = json_response
expect(product_response).to have_key(:errors)
end
it "renders the json errors on why the product could not be created" do
product_response = json_response
expect(product_response[:errors][:price]).to include "is not a number"
end
it { should respond_with 422 }
end
end
describe "PUT/PATCH #update" do
before(:each) do
@user = FactoryGirl.create :user
@product = FactoryGirl.create :product, user: @user
api_authorization_header @user.auth_token
end
context "when is successfully updated" do
before(:each) do
patch :update, { user_id: @user.id, id: @product.id,
product: { title: "An expensive TV"} }
end
it "renders the json representation for the updated user" do
product_response = json_response[:product]
expect(product_response[:title]).to eql "An expensive TV"
end
it { should respond_with 200 }
end
context "when is not updated" do
before(:each) do
patch :update, { user_id: @user.id, id: @product.id,
product: { price: "two hundred" } }
end
it "renders an errors json" do
product_response = json_response
expect(product_response).to have_key(:errors)
end
it "renders the json errors on why the user could not be created" do
product_response = json_response
expect(product_response[:errors][:price]).to include "is not a number"
end
it { should respond_with 422 }
end
end
describe "DELETE #destroy" do
before(:each) do
@user = FactoryGirl.create :user
@product = FactoryGirl.create :product, user: @user
api_authorization_header @user.auth_token
delete :destroy, { user_id: @user.id, id: @product.id }
end
it { should respond_with 204 }
end
end
产品控制器:
class Api::V1::ProductsController < ApplicationController
before_action :authenticate_with_token!, only: [:create, :update]
respond_to :json
def show
respond_with Product.find(params[:id])
end
def index
respond_with Product.all
end
def create
product = current_user.products.build(product_params)
if product.save
render json: product, status: 201, location: [:api, product]
else
render json: { errors: product.errors }, status: 422
end
end
def update
product = current_user.products.find(params[:id])
if product.update(product_params)
render json: product, status: 200, location: [:api, product]
else
render json: { errors: product.errors }, status: 422
end
end
def destroy
product = current_user.products.find(params[:id])
product.destroy
head 204
end
private
def product_params
params.require(:product).permit(:title, :price, :published)
end
end
user_serializer.rb
class UserSerializer < ActiveModel::Serializer
attributes :id, :email, :created_at, :updated_at, :auth_token
has_many :products
end
编辑:添加产品控制器