Rspec has_one 更新时关系错误
Rspec has_one relation error when updating
我有用户(这是我使用的 Devise)和个人资料模型,其中用户 has_one 个人资料作为他们的关系。 运行 rspec 测试时出现错误。以下是我在用户更新 his/her 配置文件时要处理的规范。
spec/controller/profiles_controller_spec.rb
RSpec.describe ProfilesController, type: :controller do
let(:profile) { FactoryGirl.create(:profile) }
let (:valid_attributes) { FactoryGirl.attributes_for(:profile) }
let (:invalid_attributes) { FactoryGirl.attributes_for(:profile).merge({fname: nil}) }
let(:user) { FactoryGirl.create(:user) }
let(:valid_session) { sign_in(user) }
describe "PUT #update" do
before { valid_session }
context "with valid attributes" do
it "saves valid profile" do
expect do
put :update, { id: profile.id, profile: { fname: "Cena" } }
end.to change{ profile.reload.fname }.to("Cena")
end
end
spec/factories/profiles.rb
FactoryGirl.define do
factory :profile do
user
fname "John"
lname "Doe"
avatar "my_avatar"
end
end
app/controller/profiles_controller.rb
class ProfilesController < ApplicationController
private
def user_params
params.require(:user).permit(:id, :login, :email,
profile_attributes: [
:id, :user_id, :fname, :lname, :avatar, :avatar_cache
])
end
end
这是 运行 rspec spec/controllers/accounts_controller_spec.rb
时的错误
Failures:
1) AccountsController PUT #update with valid attributes saves valid profile
Failure/Error: put :update, {id: profile.id, user_id: user.id, profile: { fname: "Cena" }}
ActionController::ParameterMissing:
param is missing or the value is empty: user
您 post 编辑的 profiles_controller.rb 代码缺少更新操作(并且 class 名称是 AccountController),但我猜您正在做类似 user.update(user_params)
.
如果是这种情况,如错误所述,从控制器规范传递的参数没有 :user
键,这就是导致错误的原因。
根据#user_params 方法和错误假设,控制器规范中传递给 post 的参数需要如下所示:
{
user: {
id: xxx, ...,
profile_attributes: {
id: xxx,
fname: xxx, ...
}
}
}
let(:user) { FactoryGirl.create(:user) }
let(:profile) { FactoryGirl.create(:profile, user_id: user.id ) }
describe "PUT #update" do
before { valid_session }
context "with valid attributes" do
it "saves valid profile" do
expect do
put :update, id: user.id, user: { profile_attributes: { user_id: user.id, fname: "Cena" } }
end.to change{ profile.reload.fname }.to("Cena")
end
end
end
我有用户(这是我使用的 Devise)和个人资料模型,其中用户 has_one 个人资料作为他们的关系。 运行 rspec 测试时出现错误。以下是我在用户更新 his/her 配置文件时要处理的规范。
spec/controller/profiles_controller_spec.rb
RSpec.describe ProfilesController, type: :controller do
let(:profile) { FactoryGirl.create(:profile) }
let (:valid_attributes) { FactoryGirl.attributes_for(:profile) }
let (:invalid_attributes) { FactoryGirl.attributes_for(:profile).merge({fname: nil}) }
let(:user) { FactoryGirl.create(:user) }
let(:valid_session) { sign_in(user) }
describe "PUT #update" do
before { valid_session }
context "with valid attributes" do
it "saves valid profile" do
expect do
put :update, { id: profile.id, profile: { fname: "Cena" } }
end.to change{ profile.reload.fname }.to("Cena")
end
end
spec/factories/profiles.rb
FactoryGirl.define do
factory :profile do
user
fname "John"
lname "Doe"
avatar "my_avatar"
end
end
app/controller/profiles_controller.rb
class ProfilesController < ApplicationController
private
def user_params
params.require(:user).permit(:id, :login, :email,
profile_attributes: [
:id, :user_id, :fname, :lname, :avatar, :avatar_cache
])
end
end
这是 运行 rspec spec/controllers/accounts_controller_spec.rb
Failures:
1) AccountsController PUT #update with valid attributes saves valid profile
Failure/Error: put :update, {id: profile.id, user_id: user.id, profile: { fname: "Cena" }}
ActionController::ParameterMissing:
param is missing or the value is empty: user
您 post 编辑的 profiles_controller.rb 代码缺少更新操作(并且 class 名称是 AccountController),但我猜您正在做类似 user.update(user_params)
.
如果是这种情况,如错误所述,从控制器规范传递的参数没有 :user
键,这就是导致错误的原因。
根据#user_params 方法和错误假设,控制器规范中传递给 post 的参数需要如下所示:
{
user: {
id: xxx, ...,
profile_attributes: {
id: xxx,
fname: xxx, ...
}
}
}
let(:user) { FactoryGirl.create(:user) }
let(:profile) { FactoryGirl.create(:profile, user_id: user.id ) }
describe "PUT #update" do
before { valid_session }
context "with valid attributes" do
it "saves valid profile" do
expect do
put :update, id: user.id, user: { profile_attributes: { user_id: user.id, fname: "Cena" } }
end.to change{ profile.reload.fname }.to("Cena")
end
end
end