2013-09-23 443 views
-1

我正在通过M. Hartl的Rails教程。运行rspec时,我不断收到“未知属性followed_id”消息。我已经看过用户模型,它和user_spec.rb文件一样好。任何指针?Ruby on Rails教程第11章:“unknown attribute:followed_id error”

user.rb文件:

class User < ActiveRecord::Base 
    attr_accessible :email, :name, :password, :password_confirmation 
    has_secure_password 

    has_many :microposts, dependent: :destroy 
    has_many :relationships, foreign_key: "follower_id", dependent: :destroy 
    has_many :followed_users, through: :relationships, source: :followed 
    has_many :reverse_relationships, foreign_key: "follower_id", 
            class_name: "Relationship", 
            dependent: :destroy 
    has_many :followers, through: :reverse_relationships, source: :follower 

    before_save { |user| user.email = email.downcase } 
    before_save :create_remember_token 

    validates :name, presence: true, length: { maximum: 50 } 
    VALID_EMAIL_REGEX = /[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+/i 
    validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false } 
    validates :password, presence: true, length: { minimum: 6 } 
    validates :password_confirmation, presence: true 

    def feed 
    Micropost.where("user_id = ?", id) 
    end 

    def following?(other_user) 
    relationships.find_by_followed_id(other_user.id) 
    end 

    def follow!(other_user) 
    relationships.create!(followed_id: other_user.id) 
    end 

    def unfollow!(other_user) 
    relationships.find_by_followed_id(other_user.id).destroy 
    end 

    private 

    def create_remember_token 
     self.remember_token = SecureRandom.urlsafe_base64 
    end 

end 

和这里的user_spec.rb文件:

require 'spec_helper' 

describe User do 
    before { @user = User.new(name: "Example user", email: "[email protected]", 
                password: "foobar", password_confirmation: "foobar") } 

    subject { @user } 

    it { should respond_to(:name) } 
    it { should respond_to(:email) } 
    it { should respond_to(:password_digest) } 
    it { should respond_to(:password) } 
    it { should respond_to(:password_confirmation) } 
    it { should respond_to(:remember_token) } 
    it { should respond_to(:admin) } 
    it { should respond_to(:authenticate) } 
    it { should respond_to(:microposts) } 
    it { should respond_to(:feed) } 
    it { should respond_to(:relationships) } 
    it { should respond_to(:followed_users) } 
    it { should respond_to(:reverse_relationships) } 
    it { should respond_to(:followers) } 
    it { should respond_to(:following?) } 
    it { should respond_to(:follow!) } 
    it { should respond_to(:unfollow!) } 

    it { should be_valid } 
    it { should_not be_admin } 

    describe "accessible attributes" do 
    it "should not allow access to admin" do 
     expect do 
     User.new(admin: true) 
     end.to raise_error(ActiveModel::MassAssignmentSecurity::Error) 
    end 
    end 

    describe "with admin attribute set to 'true'" do 
    before do 
     @user.save! 
     @user.toggle!(:admin) 
    end 

    it { should be_admin } 
    end 

    describe "remember token" do 
    before { @user.save } 
    its(:remember_token) { should_not be_blank } 
    end 

    describe "when name is not present" do 
    before { @user.name = " " } 
    it { should_not be_valid } 
    end 

    describe "when email is not present" do 
    before { @user.email = " " } 
    it { should_not be_valid } 
    end 

    describe "when name is too long" do 
    before { @user.name = "a" * 51 } 
    it { should_not be_valid } 
    end 

    describe "when email format is invalid" do 
    it "should not be valid" do 
     addresses = %w[[email protected],com user_at_foo.org [email protected] [email protected]_baz.com [email protected]+bax.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] [email protected]] 
     addresses.each do |valid_address| 
      @user.email = valid_address 
      @user.should be_valid 
     end 
    end 
    end 

    describe "when email 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 is empty" do 
    before { @user.password = @user.password_confirmation = " " } 
    it { should_not be_valid } 
    end 

    describe "when password doesn't match" do 
    before { @user.password_confirmation = "mismatch" } 
    it { should_not be_valid} 
    end 

    describe "when password is equal to nil" do 
    before { @user.password_confirmation = nil } 
    it { should_not be_valid } 
    end 

    describe "with a password that is 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 

    describe "remember token" do 
    before { @user.save } 
    its(:remember_token) { should_not be_blank } 
    end 

    describe "micropost associations" do 

    before { @user.save } 
    let!(:older_micropost) do 
     FactoryGirl.create(:micropost, user: @user, created_at: 1.day.ago) 
    end 
    let!(:newer_micropost) do 
     FactoryGirl.create(:micropost, user: @user, created_at: 1.hour.ago) 
    end 

    it "should have the right micropost in order" do 
     @user.microposts.should == [newer_micropost, older_micropost] 
    end 

    it "should be destroyed when users are destroyed" do 
     microposts = @user.microposts.dup 
     @user.destroy 
     microposts.should_not be_empty 
     microposts.each do |micropost| 
     Micropost.find_by_id(micropost.id).should be_nil 
     end 
    end 

    describe "status" do 
     let(:unfollowed_post) do 
     FactoryGirl.create(:micropost, user: FactoryGirl.create(:user)) 
     end 

     let(:followed_user) { FactoryGirl.create(:user) } 

     before do 
     @user.follow!(followed_user) 
     3.times { followed_user.microposts.create!(content: "Lorem ipsum") } 
     end 

     its(:feed) { should include(newer_micropost) } 
     its(:feed) { should include(older_micropost) } 
     its(:feed) { should_not include(unfollowed_post) } 
     its(:feed) do 
     followed_user.microposts.each do |micropost| 
      should include(micropost) 
     end 
     end 
    end 
    end 

    describe "following" do 
    let(:other_user) { FactoryGirl.create(:user) } 
    before do 
     @user.save 
     @user.follow!(other_user) 
    end 

    it { should be_following(other_user) } 
    its(:followed_users) { should include(other_user) } 

    describe "followed user" do 
     subject { other_user } 
     its(:followers) { should include(@user) } 
    end 

    describe "and unfollowing" do 
     before { @user.unfollow!(other_user) } 

     it { should_not be_following(other_user) } 
     its(:followed_users) { should_not include(other_user) } 
    end 
    end 
end 

relationship_spec.rb文件:

require 'spec_helper' 

describe Relationship do 

    let(:follower) { FactoryGirl.create(:user) } 
    let(:followed) { FactoryGirl.create(:user) } 
    let(:relationship) { follower.relationships.build(followed_id: followed.id) } 

    subject { relationship } 

    it { should be_valid } 

    describe "accessible attributes" do 
    it "should not allow access to follower_id" do 
     expect do 
     Relationship.new(follower_id: follower.id) 
     end.to raise_error(ActiveModel::MassAssignmentSecurity::Error) 
    end 
    end 

    describe "follower methods" do 
    it { should respond_to(:follower) } 
    it { should respond_to(:followed) } 
    its(:follower) { should == follower } 
    its(:followed) { should == followed } 
    end 

    describe "when followed id is not present" do 
    before { relationship.followed_id = nil } 
    it { should_not be_valid } 
    end 

    describe "when follower id is not present" do 
    before { relationship.follower_id = nil } 
    it { should_not be_valid } 
    end 
end 

运行后输出的RSpec/

Failures: 

    1) User following 
    Failure/Error: @user.follow!(other_user) 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./app/models/user.rb:43:in `follow!' 
    # ./spec/models/user_spec.rb:199:in `block (3 levels) in <top (required)>' 

    2) User following followed_users 
    Failure/Error: @user.follow!(other_user) 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./app/models/user.rb:43:in `follow!' 
    # ./spec/models/user_spec.rb:199:in `block (3 levels) in <top (required)>' 

    3) User following and unfollowing 
    Failure/Error: @user.follow!(other_user) 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./app/models/user.rb:43:in `follow!' 
    # ./spec/models/user_spec.rb:199:in `block (3 levels) in <top (required)>' 

    4) User following and unfollowing followed_users 
    Failure/Error: @user.follow!(other_user) 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./app/models/user.rb:43:in `follow!' 
    # ./spec/models/user_spec.rb:199:in `block (3 levels) in <top (required)>' 

    5) User following followed user followers 
    Failure/Error: @user.follow!(other_user) 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./app/models/user.rb:43:in `follow!' 
    # ./spec/models/user_spec.rb:199:in `block (3 levels) in <top (required)>' 

    6) User micropost associations status feed 
    Failure/Error: @user.follow!(followed_user) 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./app/models/user.rb:43:in `follow!' 
    # ./spec/models/user_spec.rb:180:in `block (4 levels) in <top (required)>' 

    7) User micropost associations status feed 
    Failure/Error: @user.follow!(followed_user) 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./app/models/user.rb:43:in `follow!' 
    # ./spec/models/user_spec.rb:180:in `block (4 levels) in <top (required)>' 

    8) User micropost associations status feed 
    Failure/Error: @user.follow!(followed_user) 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./app/models/user.rb:43:in `follow!' 
    # ./spec/models/user_spec.rb:180:in `block (4 levels) in <top (required)>' 

    9) User micropost associations status feed 
    Failure/Error: @user.follow!(followed_user) 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./app/models/user.rb:43:in `follow!' 
    # ./spec/models/user_spec.rb:180:in `block (4 levels) in <top (required)>' 

    10) Relationship 
    Failure/Error: let(:relationship) { follower.relationships.build(followed_id: followed.id) } 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./spec/models/relationship_spec.rb:7:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:9:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:11:in `block (2 levels) in <top (required)>' 

    11) Relationship when followed id is not present 
    Failure/Error: let(:relationship) { follower.relationships.build(followed_id: followed.id) } 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./spec/models/relationship_spec.rb:7:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:29:in `block (3 levels) in <top (required)>' 

    12) Relationship follower methods 
    Failure/Error: let(:relationship) { follower.relationships.build(followed_id: followed.id) } 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./spec/models/relationship_spec.rb:7:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:9:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:22:in `block (3 levels) in <top (required)>' 

    13) Relationship follower methods 
    Failure/Error: let(:relationship) { follower.relationships.build(followed_id: followed.id) } 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./spec/models/relationship_spec.rb:7:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:9:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:23:in `block (3 levels) in <top (required)>' 

    14) Relationship follower methods follower 
    Failure/Error: let(:relationship) { follower.relationships.build(followed_id: followed.id) } 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./spec/models/relationship_spec.rb:7:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:9:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:24:in `block (3 levels) in <top (required)>' 

    15) Relationship follower methods followed 
    Failure/Error: let(:relationship) { follower.relationships.build(followed_id: followed.id) } 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./spec/models/relationship_spec.rb:7:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:9:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:25:in `block (3 levels) in <top (required)>' 

    16) Relationship when follower id is not present 
    Failure/Error: let(:relationship) { follower.relationships.build(followed_id: followed.id) } 
    ActiveRecord::UnknownAttributeError: 
     unknown attribute: followed_id 
    # ./spec/models/relationship_spec.rb:7:in `block (2 levels) in <top (required)>' 
    # ./spec/models/relationship_spec.rb:34:in `block (3 levels) in <top (required)>' 

Finished in 5.58 seconds 
129 examples, 16 failures 

Failed examples: 

rspec ./spec/models/user_spec.rb:202 # User following 
rspec ./spec/models/user_spec.rb:203 # User following followed_users 
rspec ./spec/models/user_spec.rb:213 # User following and unfollowing 
rspec ./spec/models/user_spec.rb:214 # User following and unfollowing followed_users 
rspec ./spec/models/user_spec.rb:207 # User following followed user followers 
rspec ./spec/models/user_spec.rb:184 # User micropost associations status feed 
rspec ./spec/models/user_spec.rb:186 # User micropost associations status feed 
rspec ./spec/models/user_spec.rb:185 # User micropost associations status feed 
rspec ./spec/models/user_spec.rb:187 # User micropost associations status feed 
rspec ./spec/models/relationship_spec.rb:11 # Relationship 
rspec ./spec/models/relationship_spec.rb:30 # Relationship when followed id is not present 
rspec ./spec/models/relationship_spec.rb:22 # Relationship follower methods 
rspec ./spec/models/relationship_spec.rb:23 # Relationship follower methods 
rspec ./spec/models/relationship_spec.rb:24 # Relationship follower methods follower 
rspec ./spec/models/relationship_spec.rb:25 # Relationship follower methods followed 
rspec ./spec/models/relationship_spec.rb:35 # Relationship when follower id is not present 

Randomized with seed 38474 

回答

0

你创建/运行CreateRelationships迁移?确保它是正确的。如果是这样,请尝试运行rake db:test:prepare然后重新运行测试。

相关问题