RoR Hartl 튜토리얼:섹션 11.1 - rspec "연산자가 존재하지 않습니다"를 실행할 때 오류가 발생합니다.

StackOverflow https://stackoverflow.com//questions/20011120

문제

처음으로 게시합니다.Hartl의 RoR 튜토리얼을 진행 중인데 rspec 테스트가 실패하면서 막혔습니다.코드를 살펴보고 입력하는 대신 사이트에서 직접 복사하여 붙여넣었지만 여전히 오류를 찾을 수 없습니다.

도와 주셔서 감사합니다!

사양/모델/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(:authenticate) }
  it { should respond_to(:admin) }
  it { should respond_to(:microposts) }
  it { should respond_to(:feed) }
  it { should respond_to(:relationships) }
  it { should respond_to(:follow!) }
  it { should respond_to(:unfollow!) }
  it { should respond_to(:followed_users) }
  it { should respond_to(:reverse_relationships) }
  it { should respond_to(:followers) }


  it { should be_valid }
  it { should_not be_admin }

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

    it { should be_admin }
  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 be invalid" do 
        addresses = %w[user@foo,com user_at_foo.org emample.user@foo. foo@bar_baz.com foo@bar+baz.com foo@bar..com]
        addresses.each do |invalid_address|
            @user.email = invalid_address
            expect(@user).not_to 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.lst@foo.jp a+b@baz.cn]
        addresses.each do |valid_address|
            @user.email = valid_address
            expect(@user).to be_valid
        end
    end
  end

  describe "when an 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 "email address with mixed case" do
    let(:mixed_case_email) { "Foo@ExAMPle.CoM" }

    it "should be saved as lower-case" do 
        @user.email = mixed_case_email
        @user.save
        expect(@user.reload.email).to eq mixed_case_email.downcase
    end
  end

  describe "when password is not present" do 
    before do
        @user = User.new(name: "Example User", email: "user@example.com", password: " ", password_confirmation: " " )
    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 "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 eq found_user.authenticate(@user.password) }
    end

    describe "with invalid password" do
        let(:user_for_invalid_password) { found_user.authenticate("invalid") }

        it { should_not eq user_for_invalid_password }
        specify { expect(user_for_invalid_password).to 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 microposts in the right order" do
      expect(@user.microposts.to_a).to eq [newer_micropost, older_micropost]
    end

    it "should destroy associated microposts" do
      microposts = @user.microposts.to_a
      @user.destroy
      expect(microposts).not_to be_empty
      microposts.each do |micropost|
        expect(Micropost.where(id: micropost.id)).to be_empty
      end
    end

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

      its(:feed) { should include(newer_micropost) }
      its(:feed) { should include(older_micropost) }
      its(:feed) { should_not include(unfollowed_post) }
    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

앱/모델/user.rb

class User < ActiveRecord::Base
    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: "followed_id",
                                     class_name:  "Relationship",
                                     dependent:   :destroy
    has_many :followers, through: :reverse_relationships, source: :follower
    has_secure_password
    before_save { self.email = email.downcase }
    before_create :create_remember_token
    validates :name, presence: true, 
                     length: { maximum: 50 }
    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
    validates :email, presence: true, 
                      format: { with: VALID_EMAIL_REGEX }, 
                      uniqueness: { case_sensitive: false }
    validates :password, length: { minimum: 6 }

    def User.new_remember_token
        SecureRandom.urlsafe_base64
    end

    def User.encrypt(token)
        Digest::SHA1.hexdigest(token.to_s)
    end

    def feed
        # This is preliminary. See "following users" for the full implementation.
        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 = User.encrypt(User.new_remember_token)
        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 "follower methods" do
    it { should respond_to(:follower) }
    it { should respond_to(:followed) }
    its(:follower) { should eq follower }
    its(:followed) { should eq 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 사양/결과

rspec spec/ -e "User following"
Run options: include {:full_description=>/User\ following/}
..F..

Failures:

  1) User following followed user followers 
     Failure/Error: its(:followers) { should include(@user) }
     ActiveRecord::StatementInvalid:
       PG::Error: ERROR:  operator does not exist: integer = character varying
       LINE 1: ...users" INNER JOIN "relationships" ON "users"."id" = "relatio...
                                                                    ^
       HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
       : SELECT  1 AS one FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = $1 AND "users"."id" = 15 LIMIT 1
     # ./spec/models/user_spec.rb:177:in `block (4 levels) in <top (required)>'

Finished in 0.3616 seconds
5 examples, 1 failure

Failed examples:

rspec ./spec/models/user_spec.rb:177 # User following followed user followers 

Randomized with seed 7316
도움이 되었습니까?

해결책

PostgreSQL의 오류는 매우 명확합니다.

지정된 이름 및 인수 유형과 일치하는 연산자가 없습니다.명시적인 유형 캐스트를 추가해야 할 수도 있습니다.

그리고 이 JOIN 조건을 가리키고 있습니다.

"users"."id" = "relationships"."follower_id"

당신은 follower_id 당신의 열 relationships 테이블을 :string 오히려 :integer PostgreSQL은 뒤에서 암시적인 유형 변환을 수행하지 않습니다.정의를 수정하세요. follower_id 당신의 Relationship 모델(일명 귀하의 relationships 테이블).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top