验证失败:Reviewer 不能写关于你自己的评论,Reviewer 不能为空,Reviewee 不能为空

Validation failed: Reviewer cannot write a review about yourself, Reviewer can't be blank, Reviewee can't be blank

我正在为 Rails 应用程序编写控制器测试,用户可以在该应用程序中撰写关于他人(但不能为自己)的评论。

reviews_controller_spec.rb

describe "PATCH update" do
  it "redirects to user_reviews_url" do
    @user = FactoryGirl.create :user
    sign_in @user
    @user1 = FactoryGirl.create :user
    @review = FactoryGirl.create :review
    post :create, user_id:@user1.id, review:@review
    patch :update, {user_id:@user1.id, id:@review.id}, review: {:description => "john.doeexample1.com"}
    flash[:notice].should_not be_nil
    flash[:notice].should eq("Review was successfully updated.")
    response.should redirect_to(user_path(assigns(:review)))
  end
end

factories.rb

FactoryGirl.define do
  factory :review do
    skill
    stars "4"
    body "limit: 65535"
  end
  factory :skill do
    name "Cooking"
  end
  factory :experience do
    description "abcdfef"
    start_date "1989-11-23"
    level "4"
    skill
  end
  factory :user do |u|
    u.sequence(:first_name) { |n| "Michael#{n}"}
    u.last_name      "Harlt"
    u.sequence(:email) { |n|  "michael#{n}@example.com"}
    u.password "foobar123"
    u.password_confirmation "foobar123"
    u.city "Madison"
    u.state "WI"
    u.zip_code "53726"
    u.date_of_birth "23/11/1989"
  end
end

reviews_controller.rb

def update
  @skills = @user.skills
  if @review.update(review_params)
    redirect_to @user, notice: 'Review was successfully updated.'
  else
    render :edit
  end
end

review.rb

class Review < ActiveRecord::Base
  has_one :reviewer, class_name: 'User', foreign_key: "reviewer_id"
  has_one :reviewee, class_name: 'User', foreign_key: "reviewww_id"
  belongs_to :skill

  validate :user_cannot_write_review_about_themselves, on: :create

  validates_presence_of :stars, :body, :reviewer_id, :reviewee_id, :skill_id

  def user_cannot_write_review_about_themselves
    if reviewer_id == reviewee_id
      errors.add(:reviewer, "cannot write a review about yourself")
    end
  end
end

错误信息

1) ReviewsController PATCH update redirects to user_reviews_url
 Failure/Error: @review = FactoryGirl.create :review
 ActiveRecord::RecordInvalid:
   Validation failed: Reviewer cannot write a review about yourself, Reviewer can't be blank, Reviewee can't be blank
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/validations.rb:79:in `raise_record_invalid'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/validations.rb:43:in `save!'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/attribute_methods/dirty.rb:29:in `save!'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/transactions.rb:291:in `block in save!'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/transactions.rb:347:in `block in with_transaction_returning_status'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/transaction.rb:188:in `within_new_transaction'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/transactions.rb:220:in `transaction'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/transactions.rb:344:in `with_transaction_returning_status'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activerecord-4.2.0/lib/active_record/transactions.rb:291:in `save!'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/configuration.rb:14:in `block in initialize'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/evaluation.rb:15:in `[]'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/evaluation.rb:15:in `create'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/strategy/create.rb:12:in `block in result'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/strategy/create.rb:9:in `tap'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/strategy/create.rb:9:in `result'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/factory.rb:42:in `run'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/factory_runner.rb:23:in `block in run'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/activesupport-4.2.0/lib/active_support/notifications.rb:166:in `instrument'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/factory_runner.rb:22:in `run'
 # /Users/shachiagarwalla/.rvm/gems/ruby-2.2.0@zapskills/gems/factory_girl-4.5.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
 # ./spec/controllers/reviews_controller_spec.rb:11:in `block (3 levels) in <top (required)>'

如果还需要任何其他代码片段,请告诉我。

解决方案 未正确创建评论

before do
  @user = FactoryGirl.create :user
  @user1 = FactoryGirl.create :user
end
describe "PATCH update" do
  it "redirects to user_reviews_url" do
    sign_in @user1
    @review = FactoryGirl.create(:review, reviewee_id: @user.id, reviewer_id:@user1.id )
    patch :update, {user_id:@user.id, id:@review.id, review: {:description => "john.doeexample1.com"}}
    flash[:notice].should_not be_nil
    flash[:notice].should eq("Review was successfully updated.")
    response.should redirect_to(@user)
  end
end

错误是因为当您尝试 FactoryGirl.create(:review) 时,它会尝试根据您在 Review.rb 中的验证来验证它。

但是在你的工厂里你只设置了三个值:skill, stars, body.

最好(至少我喜欢)让您的基本工厂创建有效的评论。但是,这需要您为每个要创建的 Review 添加 reviewerreviewee

在你的测试中你可以这样做:

describe "PATCH update" do
  before do
    @user = FactoryGirl.create :user
    @user1 = FactoryGirl.create :user
  end
  it "redirects to user_reviews_url" do
    sign_in @user         
    post :create, review: FactoryGirl.attributes_for(:review, reviewee: @user1)
    patch :update, id:@review.id, review: {:description => "john.doeexample1.com"}
    flash[:notice].should_not be_nil
    flash[:notice].should eq("Review was successfully updated.")
    response.should redirect_to(user_path(assigns(:review)))
  end
end

此代码可能有误,我现在假设您在 create-action 中将 reviewer 设置为 current_user

如果这不起作用,请同时使用 create 操作更新您的问题。

我还鼓励您尝试在每个 it 块中保留一个动作,这个绝对可以分成两个测试。 :)