Reputation: 629
I have built an application based on the Hartl course - up to and including section 9.2 (authentication). From there I have tried to extend the functionality by adding in an Organization model. Initially I tried using the scaffold generate command line function, decided it had built too much, rolled it back and then built it by hand. I believe in this mess I may have screwed up my migrations (see below). I'm using Rails v4.1.1, Rspec 3.0.0 and Capybara 2.2.0 - all databases are postgres.
An Organization can have_many users, whereas each User belongs_to only one Organization.
I should note that using the dev environment on my own machine, I have the field for Organization working correctly during a user sign up - it creates a new user, I can view both organization and user pages correctly, and there are no errors thrown in the performance of the app. My issues begin when I'm testing using the Rspec tests - throwing a range of errors like this:
ActiveModel::MissingAttributeError:
can't write unknown attribute 'organization_id'
My models:
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
My Factories:
FactoryGirl.define do
factory :organization do
organization_name "Orgname"
end
factory :user do
association :organization
name "A Name"
email "[email protected]"
password "foobar"
password_confirmation "foobar"
end
end
An example Rspec test suite:
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 file:
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
It may be worth noting here that when I first started running the tests I was using the Rspec version recommended in Hartl's book - meaning I had to force through changes from the development DB to the test DB using the bin/rake dg:migrate RAILS_ENV=test command line function. Every time I ran this, my schema.rb file (as posted above) would lose the line
t.integer "organization_id"
and I'd have to rake the db to get it working again.
I realise there's a lot of info here, and that my questions are probably pretty dumb (I'm new to the language and framework and this is my first app) but it's driving me mad. I've spent the past week trying to find out why the tests are broken when the actual app itself is working.
Any help would be much appreciated.
Upvotes: 2
Views: 1480
Reputation: 36860
I think there's no factory for :login
... and I think that the sign_in method wants to pass in a user object.
So change your let(:login)
statement to...
let(:login) { FactoryGirl.create(:user, :organization => organization) }
Upvotes: 0
Reputation: 36860
Your before_create
method create_organization
the following line...
self.organization = Organization.create(:organization_name => Organization.organization_name) unless self.organization.present?
You're referencing a class (not object) method when you do Organization.organization_name
and no such class method exists.
You could create it in the Organization
model... it could be some default value...
def self.organization_name
"Default Organization Name"
end
Upvotes: 0