Ruby on rails RSpec/Capybara测试失败,模型设定器无方法错误
短版 我已经在我的rails应用程序中添加了一个公司模型,该应用程序位于Desive user registration视图中,使用用户模型上的accepts_nested_属性。当我手动运行安装程序时,安装程序会工作,但当我执行测试时,安装程序会失败:Ruby on rails RSpec/Capybara测试失败,模型设定器无方法错误,ruby-on-rails,rspec,devise,capybara,rspec-rails,Ruby On Rails,Rspec,Devise,Capybara,Rspec Rails,短版 我已经在我的rails应用程序中添加了一个公司模型,该应用程序位于Desive user registration视图中,使用用户模型上的accepts_nested_属性。当我手动运行安装程序时,安装程序会工作,但当我执行测试时,安装程序会失败: Failure/Error: click_button 'Sign up' NoMethodError: undefined method `owner_id=' for #<Company:0x007fe2411
Failure/Error: click_button 'Sign up'
NoMethodError:
undefined method `owner_id=' for #<Company:0x007fe2411e17b8>
长版本
最近,我在我的应用程序中添加了一个公司模型,它有两种关系。一种是说它有很多用户,另一种是说它属于某个所有者(即现有用户)
公司模式
class Company < ActiveRecord::Base
belongs_to :owner, class_name: 'User', foreign_key: 'owner_id'
has_many :users
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :company
accepts_nested_attributes_for :company
end
最后,我覆盖Desive user registrations控制器,添加设置公司所有者的逻辑
覆盖的设备注册控制器
class RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
#GET /users/sign_up
def new
# Override Devise default behaviour and create a company as well
build_resource({})
resource.build_company
respond_with self.resource
end
#POST /users/sign_up
def create
# Let devise create user and company using nested attributes
super
# Set the owner of the newly created company as new user
company = resource.company
company.owner_id = resource.id
company_saved = company.save
if company_saved == false
resource.destroy
company.destroy
return new_user_registration_path
end
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u|
u.permit(:email, :password, :password_confirmation, :company_attributes => :name)
}
end
end
类注册控制器:名称)
}
终止
终止
您是否运行了rake db:test:prepare?如果您的测试数据库在companys表中还没有owner\u id列,则可能会出现如下错误。您是否运行了rake db:test:prepare?如果您的测试数据库在companys表中还没有owner\u id列,则可能会出现如下错误。在您的测试数据库中,添加attr\u accessor:owner\u id
似乎可以解决此问题。这表明testdb模式确实是@HermanHiddema所建议的问题。代替db:test:prepare(在4.1中删除),您可以执行RAILS\u ENV=test rake db:schema:load
或类似操作来删除现有的模式并从头开始重新创建
维护测试模式!仅当模式版本与数据库中的版本不同时,才显示加载模式。因此,如果您修改了已经运行的迁移(例如),它将检测不到需要重置测试架构。在您的上,添加attr\u accessor:owner\u id
似乎可以解决问题。这表明testdb模式确实是@HermanHiddema所建议的问题。代替db:test:prepare(在4.1中删除),您可以执行RAILS\u ENV=test rake db:schema:load
或类似操作来删除现有的模式并从头开始重新创建
维护测试模式!仅当模式版本与数据库中的版本不同时,才显示加载模式。因此,如果您修改了已经运行的迁移(作为一个示例),它将检测不到需要重置测试架构。不幸的是,这对我不起作用,因为我使用的是Rails 4,因此测试数据库将自动为我管理。我相信这句话:ActiveRecord::Migration.Maintenance\u test\u schema!在RSpec的rails_helper.rb中,我也可以这样做。(但我还是试过!)。不过还是要感谢您通读它。不幸的是,这对我来说不起作用,因为我使用的是Rails 4,所以测试数据库是自动为我管理的。我相信这句话:ActiveRecord::Migration.Maintenance\u test\u schema!在RSpec的rails_helper.rb中,我也可以这样做。(但我还是试过!)。不过还是要感谢您阅读了本文。嘿,谢谢-在您发布之前,我昨晚再次尝试了一下,结果证明您是正确的:)这是由于rails中的一个bug(回滚迁移更改,然后应用,这并没有反映在测试数据库中。)rake DB:test:clone修复了它。稍后我会对Reddit做一个更完整的评论。嘿,谢谢-在你发布之前,我昨晚又试了一次,结果证明你是正确的:)这是rails中的一个错误(回滚迁移更改然后应用不会反映在测试数据库中。)rake DB:test:clone修复了它。稍后我将对Reddit进行更完整的评论。
.section.first.dark-grey.p-b-20
.container
.grid
.col-md-6.col-md-offset-3
%h2.grid-title Sign up
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
= devise_error_messages!
.form-row
= f.email_field :email, autofocus: true, class: "form-control", placeholder: "email address"
.form-row
= f.password_field :password, autocomplete: "off", class: "form-control", placeholder: "password"
.form-row
= f.password_field :password_confirmation, autocomplete: "off", class: "form-control", placeholder: "confirm password"
= f.fields_for :company_attributes do |ff|
.form-row
= ff.text_field :name, class: "form-control", placeholder: "company name"
.form-row
= f.submit "Sign up", class: "btn btn-primary btn-cons"
= render "devise/shared/links"
class RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
#GET /users/sign_up
def new
# Override Devise default behaviour and create a company as well
build_resource({})
resource.build_company
respond_with self.resource
end
#POST /users/sign_up
def create
# Let devise create user and company using nested attributes
super
# Set the owner of the newly created company as new user
company = resource.company
company.owner_id = resource.id
company_saved = company.save
if company_saved == false
resource.destroy
company.destroy
return new_user_registration_path
end
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u|
u.permit(:email, :password, :password_confirmation, :company_attributes => :name)
}
end
end