Reputation: 327
I am running into this error when running my tests. I have checked to make sure all the email_confirmation
s are spelled correctly and (unless I am crazy) they are. I'm a bit of a Rails noob, so it could be something simple.
User Model
class User < ActiveRecord::Base
attr_accessible :email, :email_confirmation, :first_name, :last_name,
:password, :password_confirmation
has_secure_password
before_save { |user| user.email = email.downcase }
validates :first_name, presence: true, length: { maximum: 25 }
validates :last_name, presence: true, length: { maximum: 25 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :email_confirmation, presence: true
validates :password, presence: true, length: { maximum: 6 }
validates :password_confirmation, presence: true
end
Rspec tests
require 'spec_helper'
describe User do
before { @user = User.new(email: "[email protected]",
first_name: "John", last_name: "Smith",
password: "foobar", password_confirmation: "foobar",
email_confirmation: "[email protected]") }
subject { @user }
it { should respond_to(:first_name) }
it { should respond_to(:last_name) }
it { should respond_to(:email) }
it { should respond_to(:email_confirmation) }
it { should respond_to(:password_digest) }
it { should respond_to(:password) }
it { should respond_to(:password_confirmation) }
it { should respond_to(:authenticate) }
it { should be_valid }
describe "when first name is not present" do
before { @user.first_name = " " }
it { should_not be_valid }
end
describe "when last name is not present" do
before { @user.last_name = " " }
it { should_not be_valid }
end
describe "when email is not present" do
before { @user.email = @user.email_confirmation = " " }
it { should_not be_valid }
end
describe "when password is not present" do
before { @user.password = @user.password_confirmation = " " }
it { should_not be_valid }
end
describe "when first_name is too long" do
before { @user.first_name = "a" * 26 }
it { should_not be_valid }
end
describe "when last_name is too long" do
before { @user.last_name = "a" * 26 }
it { should_not be_valid }
end
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user@foo,com user_at_foo.org example.user@foo.
foo@bar_baz.com foo@bar+baz.com]
addresses.each do |invalid_address|
@user.email = invalid_address
@user.should_not be_valid
end
end
end
describe "when email format is valid" do
it "should be valid" do
addresses = %w[[email protected] [email protected] [email protected] [email protected]]
addresses.each do |valid_address|
@user.email = valid_address
@user.should be_valid
end
end
end
describe "when email address is already taken" do
before do
user_with_same_email = @user.dup
user_with_same_email.email = @user.email.upcase
user_with_same_email.save
end
it { should_not be_valid }
end
describe "when password doesn't match confirmation" do
before { @user.password_confirmation = "mismatch" }
it { should_not be_valid }
end
describe "when email doesn't match confirmation" do
before { @user.email_confirmation = "[email protected]" }
it { should_not be_valid }
end
describe "when password confirmation is nil" do
before { @user.password_confirmation = nil }
it { should_not be_valid }
end
describe "when email confirmation is nil" do
before { @user.email_confirmation = nil }
it { should_not be_valid }
end
describe "with a password that's too short" do
before { @user.password = @user.password_confirmation = "a" * 5 }
it { should be_invalid }
end
describe "return value of authenticate method" do
before { @user.save }
let(:found_user) { User.find_by_email(@user.email) }
describe "with valid password" do
it { should == found_user.authenticate(@user.password) }
end
describe "with invalid password" do
let(:user_for_invalid_password) { found_user.authenticate("invalid") }
it { should_not == user_for_invalid_password }
specify { user_for_invalid_password.should be_false }
end
end
end
schema.rb
ActiveRecord::Schema.define(:version => 20130417021135) do
create_table "users", :force => true do |t|
t.string "first_name"
t.string "last_name"
t.string "email"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "password_digest"
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
end
Upvotes: 27
Views: 67102
Reputation: 52308
I had this error plenty of times when a table didn't have the column, but I had strange cause this time. For some reason, my migrations were perfect, but (weirdly) schema.rb
hadn't updated, so rake db:migrate db:seed
didn't create the column. I have no idea why that happened.
TL;DR, if your migrations are up to date, check schema.rb
and make sure it is too
Upvotes: 0
Reputation: 349
I had the same issue and this worked like magic. Add this line at the end of your migration statements for each model you would update. Resets all the cached information about columns, which will cause them to be reloaded on the next request.
<ModelName>.reset_column_information
Reference : https://apidock.com/rails/ActiveRecord/Base/reset_column_information/class
Upvotes: 7
Reputation: 403
Having just spent a ton of time debugging my own instance of this, I thought I would chime in with a third possibility.
I had done a migration correctly and verified it by inspecting my ActiveRecord
in the rails console. I had tried recreating my db from the schema many times and I had tried re-running the migration many times, all to no avail.
The problem, in my case, is that I was seeing the problem when running my unit tests, not at runtime. The issue is that my test database had gotten out of sync in my migration/rollback testing. The solution was quite simple. All I had to do was reset the test database with:
rake db:test:prepare
Upvotes: 30
Reputation: 37
I have the same message error and I fix ordering the params as same order of columns definition in database:
CONTROLLER
def create
worktime = Worktime.create(name: params[:name], workhours: params[:workhours], organization: @organization, workdays: params[:workdays])
render json: worktime
end
DATABASE
Table: worktimes
Columns:
id int(11) AI PK
name varchar(255)
workhours text
organization_id int(11)
workdays text
Upvotes: 0
Reputation: 2777
I understand that the answer above is marked correct and solves the OP's problem. But there is another cause for this error that goes unheeded in a number of stackoverflow posts on this topic. This error can occur in a polymorphic many to many when you forget to use the as: option to a has_many. For example:
class AProfile < ActiveRecord::Base
has_many :profile_students
has_many :students, through: :profile_students
end
class BProfile < ActiveRecord::Base
has_many :profile_students
has_many :students, through: :profile_students
end
class ProfileStudent < ActiveRecord::Base
belongs_to :profile, polymorphic: :true
belongs_to :student
end
class Student < ActiveRecord::Base
has_many :profile_students
has_many :aprofiles, through: :profile_students
has_many :bprofiles, through: :profile_students
end
This will give you this error:
Getting “ActiveRecord::UnknownAttributeError: unknown attribute: profile_id
when you try to do the following:
a = AProfile.new
a.students << Student.new
The solution is to add the :as option to AProfile and BProfile:
class AProfile < ActiveRecord::Base
has_many :profile_students, as: :profile
has_many :students, through: :profile_students
end
class BProfile < ActiveRecord::Base
has_many :profile_students, as: :profile
has_many :students, through: :profile_students
end
Upvotes: 11
Reputation: 11588
You're getting UnknownAttributeError
because you don't have a column in your users
table called email_confirmation
. By default, ActiveRecord will look for DB columns named the same as the attributes you use to construct the model, but this line is trying to construct a User with an attribute the database doesn't know about:
before { @user = User.new(email: "[email protected]",
first_name: "John", last_name: "Smith",
password: "foobar", password_confirmation: "foobar",
email_confirmation: "[email protected]") }
Are you really intending to save the email confirmation in the database, or are you just wanting to check that it matches email before saving it? I assume the latter, and Rails actually has built-in support for doing just that:
class User < ActiveRecord::Base
validates :email, :confirmation => true
validates :email_confirmation, :presence => true
end
See more details on the Rails Guide to Validations, or the validates_confirmation_of
API docs. (And you'll probably need to do the same thing for :password_confirmation
.)
Upvotes: 31