Rspec 测试以下模型的嵌套销毁操作
Rspec testing nested destroy action for follows model
我已经研究并看到了一个类似的问题 (),但无法找到适合我的解决方案。在我正在开发的应用程序中,我们有一个文章模型,用户可以关注文章。
我已经使用 acts_as_follower gem 来实现它,所以文章模型有一个 'followers' 方法,returns 和关注该文章的用户数组。
相关代码如下:
follows_controller
class FollowsController < ApplicationController
def create
@article = Article.find(params[:article_id])
current_user.follow(@article)
redirect_to @article
end
def destroy
@article = Article.find(params[:article_id])
current_user.stop_following(@article)
redirect_to @article
end
end
routes.rb
get '/articles/:id/history', to: 'articles#history', as: :articles_history
post '/articles/:id/undo', to: 'articles#undo', as: :undo
resources :articles do
resources :follows, :only => [:create, :destroy]
end
schema.rb
create_table "follows", force: :cascade do |t|
t.integer "followable_id", null: false
t.string "followable_type", null: false
t.integer "follower_id", null: false
t.string "follower_type", null: false
t.boolean "blocked", default: false, null: false
t.datetime "created_at"
t.datetime "updated_at"
end
spec/controllers/follows_controller_spec.rb 根据下面@Peter 的评论更新
describe '#DELETE destroy' do
it 'deletes a follow' do
@article = FactoryGirl.create(:article)
follow = FactoryGirl.create(:follow, followable_id: @article.id)
# Also, test if the action really deletes a comment.
expect{delete :destroy, id: follow.id, article_id: @article.id}.
to change{@article.followers.count}.by(-1)
end
结束
rake 路线:
article_follows POST /articles/:article_id/follows(.:format) follows#create
article_follow DELETE /articles/:article_id/follows/:id(.:format) follows#destroy
这是我在 运行 测试中遇到的错误:
失败:
1) FollowsController#DELETE destroy deletes a follow
Failure/Error: expect{delete :destroy, id: follow.id, followable_id: @article.id}.
ActionController::UrlGenerationError:
No route matches {:action=>"destroy", :controller=>"follows", :followable_id=>"2", :id=>"2"}
根据@PeterAlfvin 的以下建议添加工厂和新错误:
这是我的工厂:
FactoryGirl.define do
factory :follow do |f|
f.follower_id 1
f.followable_id 1
f.followable_type "Article"
f.follower_type "User"
end
end
这是当前错误:
1) FollowsController#DELETE destroy deletes a follow
Failure/Error: expect{delete :destroy, id: follow.id, article_id: @article.id}.
NoMethodError:
undefined method `stop_following' for nil:NilClass
# ./app/controllers/follows_controller.rb:10:in `destroy'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/implicit_render.rb:4:in `send_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/base.rb:198:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/rendering.rb:10:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/callbacks.rb:20:in `block in process_action'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:92:in `_run_callbacks'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:776:in `_run_process_action_callbacks'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:81:in `run_callbacks'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/callbacks.rb:19:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/rescue.rb:29:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications.rb:164:in `block in instrument'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications.rb:164:in `instrument'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/searchkick-0.8.7/lib/searchkick/logging.rb:107:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/activerecord-4.2.1/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/base.rb:137:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/actionview-4.2.1/lib/action_view/rendering.rb:30:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/test_case.rb:632:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/test_case.rb:65:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:19:in `block in process'
# ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:72:in `catch'
# ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:72:in `_catch_warden'
# ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:19:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/test_case.rb:532:in `delete'
# ./spec/controllers/follows_controller_spec.rb:22:in `block (4 levels) in <top (required)>'
# ./spec/controllers/follows_controller_spec.rb:22:in `block (3 levels) in <top (required)>'
# ./spec/spec_helper.rb:57:in `block (3 levels) in <top (required)>'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/generic/base.rb:15:in `cleaning'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/base.rb:92:in `cleaning'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/configuration.rb:86:in `block (2 levels) in cleaning'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/configuration.rb:87:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/configuration.rb:87:in `cleaning'
# ./spec/spec_helper.rb:56:in `block (2 levels) in <top (required)>'
我认为路由错误确实是由于指定了 followable_id
而不是您收到的评论所暗示的 article_id
。然而,随后的无方法错误也是由于在工厂调用中进行了更改。以下是您应该尝试的方法:
describe '#DELETE destroy' do
it 'deletes a follow' do
@article = FactoryGirl.create(:article)
follow = FactoryGirl.create(:follow, followable_id: @article.id)
# Test if the action really deletes a follow.
expect{delete :destroy, id: follow.id, article_id: @article.id}.
to change{@article.followers.count}.by(-1)
end
end
我已经研究并看到了一个类似的问题 (
我已经使用 acts_as_follower gem 来实现它,所以文章模型有一个 'followers' 方法,returns 和关注该文章的用户数组。
相关代码如下:
follows_controller
class FollowsController < ApplicationController
def create
@article = Article.find(params[:article_id])
current_user.follow(@article)
redirect_to @article
end
def destroy
@article = Article.find(params[:article_id])
current_user.stop_following(@article)
redirect_to @article
end
end
routes.rb
get '/articles/:id/history', to: 'articles#history', as: :articles_history
post '/articles/:id/undo', to: 'articles#undo', as: :undo
resources :articles do
resources :follows, :only => [:create, :destroy]
end
schema.rb
create_table "follows", force: :cascade do |t|
t.integer "followable_id", null: false
t.string "followable_type", null: false
t.integer "follower_id", null: false
t.string "follower_type", null: false
t.boolean "blocked", default: false, null: false
t.datetime "created_at"
t.datetime "updated_at"
end
spec/controllers/follows_controller_spec.rb 根据下面@Peter 的评论更新
describe '#DELETE destroy' do
it 'deletes a follow' do
@article = FactoryGirl.create(:article)
follow = FactoryGirl.create(:follow, followable_id: @article.id)
# Also, test if the action really deletes a comment.
expect{delete :destroy, id: follow.id, article_id: @article.id}.
to change{@article.followers.count}.by(-1)
end
结束
rake 路线:
article_follows POST /articles/:article_id/follows(.:format) follows#create
article_follow DELETE /articles/:article_id/follows/:id(.:format) follows#destroy
这是我在 运行 测试中遇到的错误:
失败:
1) FollowsController#DELETE destroy deletes a follow
Failure/Error: expect{delete :destroy, id: follow.id, followable_id: @article.id}.
ActionController::UrlGenerationError:
No route matches {:action=>"destroy", :controller=>"follows", :followable_id=>"2", :id=>"2"}
根据@PeterAlfvin 的以下建议添加工厂和新错误:
这是我的工厂:
FactoryGirl.define do
factory :follow do |f|
f.follower_id 1
f.followable_id 1
f.followable_type "Article"
f.follower_type "User"
end
end
这是当前错误:
1) FollowsController#DELETE destroy deletes a follow
Failure/Error: expect{delete :destroy, id: follow.id, article_id: @article.id}.
NoMethodError:
undefined method `stop_following' for nil:NilClass
# ./app/controllers/follows_controller.rb:10:in `destroy'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/implicit_render.rb:4:in `send_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/base.rb:198:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/rendering.rb:10:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/callbacks.rb:20:in `block in process_action'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:117:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:505:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:92:in `_run_callbacks'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:776:in `_run_process_action_callbacks'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/callbacks.rb:81:in `run_callbacks'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/callbacks.rb:19:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/rescue.rb:29:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications.rb:164:in `block in instrument'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
# ./.bundle/gems/ruby/2.2.0/gems/activesupport-4.2.1/lib/active_support/notifications.rb:164:in `instrument'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/searchkick-0.8.7/lib/searchkick/logging.rb:107:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/activerecord-4.2.1/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/abstract_controller/base.rb:137:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/actionview-4.2.1/lib/action_view/rendering.rb:30:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/test_case.rb:632:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/test_case.rb:65:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:19:in `block in process'
# ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:72:in `catch'
# ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:72:in `_catch_warden'
# ./.bundle/gems/ruby/2.2.0/gems/devise-3.4.1/lib/devise/test_helpers.rb:19:in `process'
# ./.bundle/gems/ruby/2.2.0/gems/actionpack-4.2.1/lib/action_controller/test_case.rb:532:in `delete'
# ./spec/controllers/follows_controller_spec.rb:22:in `block (4 levels) in <top (required)>'
# ./spec/controllers/follows_controller_spec.rb:22:in `block (3 levels) in <top (required)>'
# ./spec/spec_helper.rb:57:in `block (3 levels) in <top (required)>'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/generic/base.rb:15:in `cleaning'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/base.rb:92:in `cleaning'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/configuration.rb:86:in `block (2 levels) in cleaning'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/configuration.rb:87:in `call'
# ./.bundle/gems/ruby/2.2.0/gems/database_cleaner-1.3.0/lib/database_cleaner/configuration.rb:87:in `cleaning'
# ./spec/spec_helper.rb:56:in `block (2 levels) in <top (required)>'
我认为路由错误确实是由于指定了 followable_id
而不是您收到的评论所暗示的 article_id
。然而,随后的无方法错误也是由于在工厂调用中进行了更改。以下是您应该尝试的方法:
describe '#DELETE destroy' do
it 'deletes a follow' do
@article = FactoryGirl.create(:article)
follow = FactoryGirl.create(:follow, followable_id: @article.id)
# Test if the action really deletes a follow.
expect{delete :destroy, id: follow.id, article_id: @article.id}.
to change{@article.followers.count}.by(-1)
end
end