-1

我正在阅读 M. Hartl 的 Rails 教程。运行 rspec 时,我不断收到“未知属性 follow_id”消息。我查看了 User 模型,它似乎和 user_spec.rb 文件一样好。任何指针?

用户.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+\-.]+@[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: "user@example.com", 
                                                  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[user@foo,com user_at_foo.org example.user@foo. foo@bar_baz.com foo@bar+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[user@foo.COM a_us-ER@f.b.org frst.last@foo.jp a+b@bax.cn first@co.uk]
        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
4

1 回答 1

0

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

于 2013-09-24T00:34:00.027 回答