我在测试 CommentsController :
时遇到了这个问题失败/错误:redirect_to user_path(@ comment.user),注意:'你的 评论已成功添加!' ActionController的:: UrlGenerationError: 没有路由匹配{:action =>“show”,:controller =>“users”,:id => nil} 缺少必需的键:[:id]
这是我在控制器中的方法:
def create
if params[:parent_id].to_i > 0
parent = Comment.find_by_id(params[:comment].delete(:parent_id))
@comment = parent.children.build(comment_params)
else
@comment = Comment.new(comment_params)
end
@comment.author_id = current_user.id
if @comment.save
redirect_to user_path(@comment.user), notice: 'Your comment was successfully added!'
else
redirect_to user_path(@comment.user), notice: @comment.errors.full_messages.join
end
end
这是我的 RSpec :
context "User logged in" do
before :each do
@user = create(:user)
sign_in @user
end
let(:comment) { create(:comment, user: @user, author_id: @user.id) }
let(:comment_child) { create(:comment_child, user: @user, author_id: @user.id, parent_id: comment.id) }
describe "POST #create" do
context "with valid attributes" do
it "saves the new comment object" do
expect{ post :create, comment: attributes_for(:comment), id: @user.id}.to change(Comment, :count).by(1)
end
it "redirect to :show view " do
post :create, comment: attributes_for(:comment), user: @user
expect(response).to redirect_to user_path(comment.user)
end
end
...
end
end
我的评论型号:
class Comment < ActiveRecord::Base
belongs_to :user
acts_as_tree order: 'created_at DESC'
VALID_REGEX = /\A^[\w \.\-@:),.!?"']*$\Z/
validates :body, presence: true, length: { in: 2..240}, format: { with: VALID_REGEX }
end
如何将user_id
添加到该请求中?当我将控制器redirect_to user_path(@comment.user)
中的代码更改为redirect_to user_path(current_user)
时 - 测试通过。我可以在评论控制器中redirect_to
用户吗?有可能做得对吗?谢谢你的时间。
答案 0 :(得分:2)
基本上,错误是由@comment.user
为零而导致的。
让我们通过清理规范来开始修复它:
context "User logged in" do
# declare lets first.
let(:user) { create(:user) }
let(:comment) { create(:comment, user: user, author: user) }
# use do instead of braces when it does not fit on one line.
let(:comment_child) do
# use `user: user` instead of `user_id: user.id`.
# the latter defeats the whole purpose of the abstraction.
create(:comment_child, user: user, author: user, parent: comment)
end
before { sign_in(user) }
describe "POST #create" do
context "with valid attributes" do
it "saves the new comment object" do
expect do
post :create, comment: attributes_for(:comment)
end.to change(Comment, :count).by(1)
end
it "redirects to the user" do
post :create, comment: attributes_for(:comment)
expect(response).to redirect_to user
end
end
end
end
您通常应避免使用实例变量,而在大多数情况下使用lets
。使用混合只会增加混乱,因为很难看到什么是延迟加载甚至实例化的地方。
然后我们可以处理实施:
def create
@comment = current_user.comments.new(comment_params)
if @comment.save
redirect_to @comment.user, notice: 'Your comment was successfully added!'
else
# ...
end
end
private
def comment_params
# note that we don't permit the user_id to be mass assigned
params.require(:comment).permit(:foo, :bar, :parent_id)
end
基本上你可以减少很多过度复杂:
before_action :authenticate_user!
。comments
键中包裹参数。redirect_to @some_model_instance
并让rails执行其多态路由魔术。parent_id
,请让ActiveRecord抛出错误。 您的评论模型是否真的需要user
和author
关系?当然其中一个就足够了。