Ruby on rails 尝试测试嵌套属性时,Rspec引发未知属性错误
我已经建立了一个基于Hartl课程的应用程序-包括第9.2节(认证)。在此基础上,我尝试通过添加组织模型来扩展功能。最初,我尝试使用scaffold generate命令行函数,认为它构建的太多,将其回滚,然后手动构建。我相信在这种混乱中,我可能把我的迁移搞砸了(见下文)。我使用的是Rails v4.1.1、Rspec 3.0.0和Capybara 2.2.0——所有数据库都是postgres 一个组织可以有多个用户,而每个用户只属于一个组织 我应该注意的是,在我自己的机器上使用dev环境,在用户注册期间,我有一个正确运行组织的字段-它创建了一个新用户,我可以正确查看组织和用户页面,并且在应用程序的性能中没有抛出错误。当我使用Rspec测试时,我的问题就开始了——抛出一系列错误,如下所示:Ruby on rails 尝试测试嵌套属性时,Rspec引发未知属性错误,ruby-on-rails,ruby,rspec,Ruby On Rails,Ruby,Rspec,我已经建立了一个基于Hartl课程的应用程序-包括第9.2节(认证)。在此基础上,我尝试通过添加组织模型来扩展功能。最初,我尝试使用scaffold generate命令行函数,认为它构建的太多,将其回滚,然后手动构建。我相信在这种混乱中,我可能把我的迁移搞砸了(见下文)。我使用的是Rails v4.1.1、Rspec 3.0.0和Capybara 2.2.0——所有数据库都是postgres 一个组织可以有多个用户,而每个用户只属于一个组织 我应该注意的是,在我自己的机器上使用dev环境,在用
ActiveModel::MissingAttributeError:
can't write unknown attribute 'organization_id'
我的模型:
class Organization < ActiveRecord::Base
validates :organization_name, presence: true, length: { maximum: 50 }
has_many :users
end
class User < ActiveRecord::Base
belongs_to :organization
accepts_nested_attributes_for :organization
before_save { self.email = email.downcase }
before_create :create_remember_token, :create_organization
validates :name, presence: true, length: {maximum: 50}
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, format: {with: VALID_EMAIL_REGEX}, uniqueness: {case_sensitive: false}
has_secure_password
validates :password, length: {minimum: 6}
def create_organization
self.organization = Organization.create(:organization_name => Organization.organization_name) unless self.organization.present?
end
Rspec测试套件示例:
describe "edit" do
let(:organization) { FactoryGirl.create(:organization) }
let(:login) { FactoryGirl.create(:login,
:organization => organization,
:user => FactoryGirl.create(:user)) }
before do
sign_in login
visit edit_user_path (user)
end
My schema.rb文件:
ActiveRecord::Schema.define(version: 20140619041326) do
create_table "organizations", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.string "organization_name"
end
create_table "users", force: true do |t|
t.string "name"
t.string "email"
t.datetime "created_at"
t.datetime "updated_at"
t.string "password_digest"
t.integer "organization_id"
t.string "remember_token"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["organization_id"], name: "index_users_on_organization_id", using: :btree
add_index "users", ["remember_token"], name: "index_users_on_remember_token", using: :btree
end
这里可能值得注意的是,当我第一次开始运行测试时,我使用的是Hartl书中推荐的Rspec版本,这意味着我必须使用bin/rake dg:migrate RAILS_ENV=test命令行函数强制完成从开发数据库到测试数据库的更改。每次运行这个程序时,我的schema.rb文件(如上所述)都会丢失该行
t.integer“组织id”
我必须用耙子清理数据库才能让它重新工作
我意识到这里有很多信息,我的问题可能相当愚蠢(我对语言和框架还不熟悉,这是我的第一个应用程序),但这让我发疯。在过去的一周里,我一直在试图找出为什么在实际应用程序本身运行时测试失败
任何帮助都将不胜感激。您的
在创建之前
方法创建组织
下一行
self.organization = Organization.create(:organization_name => Organization.organization_name) unless self.organization.present?
执行Organization.Organization\u name
时引用的是类(而不是对象)方法,并且不存在此类类方法
您可以在组织
模型中创建它。。。它可能是某个默认值
def self.organization_name
"Default Organization Name"
end
我认为没有工厂用于
:登录。。。我认为sign_-in方法想要传入一个用户对象
因此,将您的let(:login)
语句更改为
let(:login) { FactoryGirl.create(:user, :organization => organization) }
我发现了这个问题-显然Rails 4不会使用ActiveRecord::Migration.Maintenance\u test\u模式自动更新模式代码>在spec_helper中-相反,您仍然需要使用“rakedb:test:prepare”。然而,虽然这消除了我的一些错误,我仍然得到3个主要错误:1)它不喜欢我的工厂“登录”(我复制了其他代码,似乎表明这可以工作)2)在用户页面rspec测试中,它找不到字段“organization name”3。)它说“organization_name”方法对于“create_organization”是未定义的上面列出的功能有什么想法吗?谢谢。我使用create_组织代码的目的是确保任何注册现有组织的帐户的人都属于该组织(而不是复制该组织)。设置默认值会有任何负面影响吗?或者,没有这个create_组织代码,有没有更好的方法来实现我的目标?事实上,如果在调用create之前已经为用户分配了一个组织,那么它的行为将与预期的一样。你是说如果没有分配组织,但组织表中至少有一个组织,你想使用组织表中的第一条记录吗?不,我只是担心这会让人们注册而不包括组织名称,然后被作为组的一部分使用“默认组织名称“相反。目前,这不会产生任何影响,但最终我希望第一个注册任何组织的用户成为管理员用户,并能够在整个用户群中运行报告。如果省略组织名称的人仍然可以注册,这将产生一个问题。好的,代码organization.organization\u name
不正确,因为没有这样的类方法。听起来,作为注册过程的一部分,用户可以输入组织名称?你想用它来建立组织记录吗?是的,没错。一个(全新的)用户来到这个网站,同时注册了他自己的用户名和他所属的组织名称。试图注册同一组织的后续用户将被发送到队列,等待第一个用户批准(第一个用户最终将成为管理员)。代码中的要点是试图防止出现多个同名组织。谢谢。实际上,我通过向用户工厂添加一个trait,并传递一个新用户和trait来解决这个问题。您的方法会更好,还是我应该让代码保持原样?
let(:login) { FactoryGirl.create(:user, :organization => organization) }