在测试环境中,Rails模型创建和新返回nil

时间:2014-10-07 19:48:40

标签: ruby-on-rails ruby ruby-on-rails-3 rspec

我有一个模型规范失败了“未定义的方法'保存'为nil:NilClass'。”这发生在类方法'create_and_send_self_eval'中。该方法正在创建一个新的评估,但它总是在测试环境中返回nil。我也试过用'创造','创造!'他们也返回零。但是,这仅发生在测试环境中。在开发环境中,它返回正确的对象。我正在使用rspec 3.1.5,rails 4.1.6和ruby 2.1.2。

我已经包含了类和我的调试输出的代码。有什么建议吗?

Evaluation.rb

class Evaluation < ActiveRecord::Base
  has_one :evaluator
  validates_uniqueness_of :access_key
  validates_presence_of :participant_id

  before_validation :set_access_key, on: :create

  def send_invite
    return true
  end

  def self.create_and_send_self_eval(participant)
    evaluation = self.new do |e|
      e.participant_id = participant.id
      e.evaluator = participant
    end
    if evaluation.nil?
      binding.pry
    end
    evaluation.save
  end

  private

    def set_access_key
      return if access_key.present?

      begin
        self.access_key = SecureRandom.hex(8)
      end while self.class.exists?(access_key: self.access_key)
    end

end

在测试环境中使用pry调试输出

[1] pry(Evaluation)> participant
=> #<Participant id: 167, first_name: "Puff", last_name: "Daddy", evaluation_url: nil, created_at: "2014-10-07 19:43:47", updated_at: "2014-10-07 19:43:47">
[2] pry(Evaluation)> Evaluation.new
=> nil
[3] pry(Evaluation)> Evaluation.create(participant_id: participant.id)
NoMethodError: undefined method `save' for nil:NilClass
from /Users/diyahm/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.6/lib/active_record/persistence.rb:34:in `create'
[4] pry(Evaluation)> Evaluation.create!(participant_id: participant.id)
NoMethodError: undefined method `save!' for nil:NilClass
from /Users/diyahm/.rvm/gems/ruby-2.1.2/gems/activerecord-4.1.6/lib/active_record/validations.rb:41:in `create!'

rails控制台中的调试输出

2.1.2 :005 > p = Participant.last
  SQL (0.9ms)  SELECT  "participants"."id" AS t0_r0, "participants"."first_name" AS t0_r1, "participants"."last_name" AS t0_r2, "participants"."evaluation_url" AS t0_r3, "participants"."created_at" AS t0_r4, "participants"."updated_at" AS t0_r5, "evaluators"."id" AS t1_r0, "evaluators"."email" AS t1_r1, "evaluators"."created_at" AS t1_r2, "evaluators"."updated_at" AS t1_r3, "evaluators"."actable_id" AS t1_r4, "evaluators"."actable_type" AS t1_r5, "evaluators"."evaluation_id" AS t1_r6 FROM "participants" LEFT OUTER JOIN "evaluators" ON "evaluators"."actable_id" = "participants"."id" AND "evaluators"."actable_type" = 'Participant'  ORDER BY "participants"."id" DESC LIMIT 1
 => #<Participant id: 3, first_name: "Puff", last_name: "Daddy", evaluation_url: nil, created_at: "2014-10-06 06:32:40", updated_at: "2014-10-06 06:32:40"> 
2.1.2 :006 > Evaluation.new
 => #<Evaluation id: nil, participant_id: nil, access_key: nil, created_at: nil, updated_at: nil> 
2.1.2 :007 > Evaluation.create(participant_id: p.id)
   (0.2ms)  BEGIN
  Evaluation Exists (2.1ms)  SELECT  1 AS one FROM "evaluations"  WHERE "evaluations"."access_key" = 'c688b05ee4625c60' LIMIT 1
  Evaluation Exists (0.3ms)  SELECT  1 AS one FROM "evaluations"  WHERE "evaluations"."access_key" = 'c688b05ee4625c60' LIMIT 1
  SQL (1.7ms)  INSERT INTO "evaluations" ("access_key", "created_at", "participant_id", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["access_key", "c688b05ee4625c60"], ["created_at", "2014-10-07 19:47:15.877706"], ["participant_id", 3], ["updated_at", "2014-10-07 19:47:15.877706"]]
   (2.3ms)  COMMIT
 => #<Evaluation id: 4, participant_id: 3, access_key: "c688b05ee4625c60", created_at: "2014-10-07 19:47:15", updated_at: "2014-10-07 19:47:15">

在方法开始时调试输出

[1] pry(Evaluation)> self
=> Evaluation(id: integer, participant_id: integer, access_key: string, created_at: datetime, updated_at: datetime)
[2] pry(Evaluation)> self.class
=> Class
[3] pry(Evaluation)> self.connection
=> #<ActiveRecord::ConnectionAdapters::PostgreSQLAdapter:0x007f8158eb8ee0

[4] pry(Evaluation)> Evaluation
=> Evaluation(id: integer, participant_id: integer, access_key: string, created_at: datetime, updated_at: datetime)
[5] pry(Evaluation)> Evaluation.class
=> Class
[6] pry(Evaluation)> Evaluation.connection
=> #<ActiveRecord::ConnectionAdapters::PostgreSQLAdapter:0x007f8158eb8ee0

我没有显示self.connection或Evaluation.connection的整个输出。但连接正确返回。

2 个答案:

答案 0 :(得分:2)

这个问题的答案与测试的编写方式有关。在我的规范中,我正在检查是否&#34; new&#34;被称为评估。因为,我使用的是rspec-mocks,实际上并没有创建评估。通过更改测试来测试输出结果来解决此问题。

答案 1 :(得分:0)

尝试这样做:

evaluation = self.new.tap do |e|
  e.participant_id = participant.id
  e.evaluator = participant
end

使用Object#tap应该保证您将评估设置为对象而不是块的返回值。

相关问题