尝试测试嵌套属性时Rspec抛出的未知属性错误

时间:2014-06-24 07:56:30

标签: ruby-on-rails ruby rspec

我已经基于Hartl课程构建了一个应用程序 - 包括第9.2节(身份验证)。从那里我尝试通过添加组织模型来扩展功能。最初我尝试使用scaffold生成命令行函数,确定它已构建太多,将其回滚然后手动构建它。我相信这个混乱我可能搞砸了我的迁移(见下文)。我使用Rails v4.1.1,Rspec 3.0.0和Capybara 2.2.0 - 所有数据库都是postgres。

组织可以拥有多个用户,而每个用户只拥有一个组织。

我应该注意到在我自己的机器上使用开发环境,我在组织用户注册期间可以正常工作 - 它创建了一个新用户,我可以正确地查看组织和用户页面,而且没有应用程序性能中出现的错误。当我使用Rspec测试进行测试时,我的问题就开始了 - 抛出一系列错误:

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

我的工厂:

FactoryGirl.define do
  factory :organization do
    organization_name "Orgname"
  end
  factory :user do
    association :organization
    name "A Name"
    email "name@example.com"
    password "foobar"
    password_confirmation "foobar"
  end
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

我的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从开发DB到测试DB的更改/ rake dg:migrate RAILS_ENV = test命令行函数。每次运行时,我的schema.rb文件(如上所述)都会丢失行

t.integer "organization_id"

我必须耙db才能让它再次运行。

我意识到这里有很多信息,而且我的问题可能非常愚蠢(我是语言和框架的新手,这是我的第一个应用程序)但它驱使我狂。过去一周我一直试图找出实际应用本身工作时测试被破坏的原因。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

您的before_create方法create_organization以下一行......

  self.organization = Organization.create(:organization_name => Organization.organization_name) unless self.organization.present?

当您执行Organization.organization_name并且不存在此类方法时,您正在引用类(非对象)方法。

您可以在Organization模型中创建它...它可能是默认值...

def self.organization_name
  "Default Organization Name"
end

答案 1 :(得分:0)

我认为:login没有工厂......而且我认为sign_in方法想要传入用户对象。

因此,请将您的let(:login)声明更改为...

let(:login) { FactoryGirl.create(:user, :organization => organization) }