Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/52.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 尝试在Rails应用程序的数据库中保存ActiveRecord时出现NoMethodError_Ruby On Rails_Ruby_Validation_Ruby On Rails 5 - Fatal编程技术网

Ruby on rails 尝试在Rails应用程序的数据库中保存ActiveRecord时出现NoMethodError

Ruby on rails 尝试在Rails应用程序的数据库中保存ActiveRecord时出现NoMethodError,ruby-on-rails,ruby,validation,ruby-on-rails-5,Ruby On Rails,Ruby,Validation,Ruby On Rails 5,我正在构建的应用程序是一个非常简单的网站监控工具,包含用户、警报和爬网。我创建了一个Rake任务,负责按指定的时间间隔对站点进行爬网,它工作正常,当使用Rake crawl\u next手动运行时,会将爬网历史保存到数据库中 集成逻辑以检查爬网是否超过用户指定的限制或是否存在错误&然后通过电子邮件发送给用户后,我无法再将爬网记录保存到数据库中。在运行rake任务时,我得到了一个针对false:false类的NoMethodError:undefined方法'clear',我无法确定其来源。根据控

我正在构建的应用程序是一个非常简单的网站监控工具,包含用户、警报和爬网。我创建了一个Rake任务,负责按指定的时间间隔对站点进行爬网,它工作正常,当使用
Rake crawl\u next
手动运行时,会将爬网历史保存到数据库中

集成逻辑以检查爬网是否超过用户指定的限制或是否存在错误&然后通过电子邮件发送给用户后,我无法再将爬网记录保存到数据库中。在运行rake任务时,我得到了一个针对false:false类的
NoMethodError:undefined方法'clear',我无法确定其来源。根据控制台的输出,我认为是验证失败了,但我无法确定是什么验证导致了验证失败。我希望一个更有经验的开发人员能为我指明正确的方向

我已经隔离了将爬网记录保存到数据库的问题…我想

  • 我使用了
    pry
    来检查输入和变量,似乎没有任何问题
  • 我已经注释掉了爬网模型上的
    after_save
    操作,以消除可能的警报模型代码错误
  • 在Rails控制台中,我尝试使用mass assignment和
    .create
    方法手动创建新爬网。它以同样的方式失败
  • 使用Rails5.1.5W/Ruby2.5.0p0、c9.io IDE
控制台输出:

** Invoke crawl_next (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute crawl_next
rake aborted!
NoMethodError: undefined method `clear' for false:FalseClass
/usr/local/rvm/gems/ruby-2.5.0/gems/activemodel-5.1.5/lib/active_model/validations.rb:334:in `valid?'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/validations.rb:65:in `valid?'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/validations.rb:82:in `perform_validations'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/validations.rb:44:in `save'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/attribute_methods/dirty.rb:35:in `save'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/transactions.rb:308:in `block (2 levels) in save'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/transactions.rb:384:in `block in with_transaction_returning_status'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/connection_adapters/abstract/database_statements.rb:235:in `block in transaction'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/connection_adapters/abstract/transaction.rb:194:in `block in within_new_transaction'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/connection_adapters/abstract/transaction.rb:191:in `within_new_transaction'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/connection_adapters/abstract/database_statements.rb:235:in `transaction'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/transactions.rb:210:in `transaction'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/transactions.rb:381:in `with_transaction_returning_status'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/transactions.rb:308:in `block in save'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/transactions.rb:323:in `rollback_active_record_state!'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/transactions.rb:307:in `save'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/suppressor.rb:42:in `save'
/home/ubuntu/workspace/web_monitor/lib/tasks/scheduler.rake:19:in `block (2 levels) in <top (required)>'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/relation/delegation.rb:39:in `each'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/relation/delegation.rb:39:in `each'
/home/ubuntu/workspace/web_monitor/lib/tasks/scheduler.rake:5:in `block in <top (required)>'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:251:in `block in execute'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:251:in `each'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:251:in `execute'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:195:in `block in invoke_with_call_chain'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:188:in `invoke_with_call_chain'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:181:in `invoke'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:160:in `invoke_task'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:116:in `each'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:116:in `block in top_level'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:125:in `run_with_threads'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:110:in `top_level'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:83:in `block in run'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:186:in `standard_exception_handling'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:80:in `run'
/usr/local/rvm/gems/ruby-2.5.0@global/gems/rake-12.3.0/exe/rake:27:in `<top (required)>'
/usr/local/rvm/rubies/ruby-2.5.0/bin/rake:29:in `load'
/usr/local/rvm/rubies/ruby-2.5.0/bin/rake:29:in `<main>'
Tasks: TOP => crawl_next
**下一次调用爬网(第一次)
**调用环境(第一次)
**执行环境
**下一步执行爬网
雷克流产了!
NoMethodError:false:FalseClass的未定义方法“clear”
/usr/local/rvm/gems/ruby-2.5.0/gems/activemodel-5.1.5/lib/active\u model/validations.rb:334:in'valid'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/validations.rb:65:in'valid'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/validations.rb:82:in“perform\u validations”
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/validations.rb:44:in“保存”
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/attribute\u methods/dirty.rb:35:在“保存”中
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_record/transactions.rb:308:在“保存中的块(两个级别)”中
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/transactions.rb:384:在“带事务返回状态的块中”
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/connection\u adapters/abstract/database\u语句。rb:235:“事务中的块”中
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/connection\u adapters/abstract/transaction.rb:194:在“block in in in_new\u transaction”中
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/2.5.0/monitor.rb:226:in'mon_synchronize'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/connection\u adapters/abstract/transaction.rb:191:in'within_new\u transaction'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_-record/connection_-adapters/abstract/database_语句。rb:235:在“事务”中
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/transactions.rb:210:in“transaction”
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/transactions.rb:381:in“with\u transaction\u returning\u status”
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/transactions.rb:308:in'block in save'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/transactions.rb:323:处于“回滚”活动记录状态
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_-record/transactions.rb:307:in'save'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active\u record/suppressor.rb:42:在“保存”中
/home/ubuntu/workspace/web_monitor/lib/tasks/scheduler.rake:19:in'block(2层)in'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_-record/relation/delegation.rb:39:in'each'
/usr/local/rvm/gems/ruby-2.5.0/gems/activerecord-5.1.5/lib/active_-record/relation/delegation.rb:39:in'each'
/home/ubuntu/workspace/web_monitor/lib/tasks/scheduler.rake:5:in'block-in'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:251:在“执行中的块”中
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:251:in'each'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:251:in'execute'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:195:in`block in invoke_with_call_chain'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/2.5.0/monitor.rb:226:in'mon_synchronize'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:188:in“调用链调用”
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/task.rb:181:in“invoke”
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:160:in'invoke_task'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:116“块(2级)顶层”
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:116:in'each'
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:116:在“顶级块”中
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:125:在“使用线程运行”中
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:110“顶级”
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:83:在“运行中的块”中
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0/gems/rake-12.3.0/lib/rake/application.rb:186:在“标准异常处理”中
/usr/local/rvm/rubies/ruby-2.5.0/lib/ruby/gems/2.5.0
desc "perform crawls for active alerts if their interval has passed"
task :crawl_next => :environment do
  alerts = Alert.where(active: true).includes(:crawls)

  alerts.each do |alert|
    last = alert.crawls.last

    last_crawl_time = last.crawl_time if !last.nil?

    if last.nil? ||
       (last_crawl_time + alert.crawl_interval_mins*60) < Time.now + 1
      crawl_stats = alert.crawl
    end

    if crawl_stats
      crawl = Crawl.new(crawl_stats)
      crawl.save

      if crawl.exceeds_limits? || crawl.errors
        UserMailer.crawl_alert(alert, crawl).deliver_later
      end
    else
      alert.deactivate
    end
  end
end
class Crawl < ActiveRecord::Base
  belongs_to :alert

  after_save :update_alert_last_crawl

  def update_alert_last_crawl
    alert = self.alert
    alert.update(last_crawl: self.crawl_time)
  end

  def exceeds_limits?
    self.resp_time_ms > self.alert.response_time_threshold_ms
  end

  def errors
    self.resp_code != "200"
  end
end
class Alert < ActiveRecord::Base
  has_many :user_alerts
  has_many :users, through: :user_alerts, dependent: :destroy
  has_many :crawls, dependent: :destroy

  before_save :activate # TODO: don't activate all alerts before save

  validate :valid_url? # Using custom method instead of valid url gem

  validates :crawl_interval_mins, presence: true, inclusion: {in: [10, 30, 60]}
  validates :notify_emails, presence: true, length: {minimum: 6}
  validates :name, presence: true, length: {minimum: 2}

  def activate
    self.active = true
  end

  def deactivate
    self.active = false
    UserMailer.alert_deactivated(self).deliver_later
  end

  # Return a hash corresponding to a Crawl's schema, to be used in creating
  # a new crawl record
  def crawl
    data = {}
    resp = nil

    time = Benchmark.measure do
      begin
        resp = HTTParty.get(self.url)
      rescue => e
        data = crawl_error_info(e)
      end
    end

    {
      alert_id: self.id,
      crawl_time: Time.now.to_s,
      resp_code: data[:resp_code] || resp.code,
      resp_time_ms: data[:resp_time_ms] || time.real * 1_000,
      resp_status: data[:resp_status] || resp.message,
      resp_size_kb: data[:resp_size_kb] || resp.size # TODO: convert to mb
    }
  end

  def valid_url?
    if !self.url.match(/^(((http|https):\/\/|)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}(:[0-9]{1,5})?(\/.*)?)$/i)
      errors.add(:url, "not valid")
    end
  end

  def crawl_error_info(e)
    if e.class == SocketError
      return {
        resp_code: 443,
        resp_time_ms: 0,
        resp_status: "NAME/SVC NOT KNOWN",
        resp_size_kb: 0 # TODO: convert to mb
      }
    end
  end
end
crawl.save
def valid?(context = nil)
  current_context, self.validation_context = validation_context, context
  errors.clear
  run_validations!
ensure
  self.validation_context = current_context
end
  def errors
    self.resp_code != "200"
  end
if crawl.exceeds_limits? || crawl.bad_response_code?