Ruby on rails RSpec/Capybara测试失败,模型设定器无方法错误

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

短版

我已经在我的rails应用程序中添加了一个公司模型,该应用程序位于Desive user registration视图中,使用用户模型上的accepts_nested_属性。当我手动运行安装程序时,安装程序会工作,但当我执行测试时,安装程序会失败:

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