title: NoMethodError when attempting ActiveRecord save in database in Rails app
body: <p>The app I'm building is a very simple website monitoring tool with Users, Alerts, and Crawls. I created a Rake task to take care of crawling the sites at specified intervals, and it was working fine, saving the crawl history to the db when manually run with <code>rake crawl_next</code>.</p>
  
  <p>After integrating logic to check if the crawl is over a user's specified limits or there are errors &amp; then emailing the user, I'm no longer able to save a crawl record to the database. I'm getting a <code>NoMethodError: undefined method 'clear' for false:FalseClass</code> when running the rake task, which I can't pinpoint the source of. Based on the console output, I presume it's some failing validation, but I can't determine what validation might be causing it to fail. I'm hoping a more experienced Dev can point me in the right direction.</p>
  
  <p>I've isolated the issue with the saving of the crawl record to the database...I think.</p>
  
  <ul>
  <li>I've used <code>pry</code> to inspect the inputs &amp; variables, and nothing seems amiss.</li>
  <li>I've commented out the <code>after_save</code> action on the crawl model to eliminate possible alert model code errors.</li>
  <li>In the Rails console, I've tried manually creating new crawls using both mass assignment &amp; the <code>.create</code> method. It fails the same way.</li>
  <li>Using Rails 5.1.5 w/ Ruby 2.5.0p0, c9.io IDE</li>
  </ul>
  
  <p>Console output:</p>
  
  <pre><code>** 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 &lt;top (required)&gt;'
  /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 &lt;top (required)&gt;'
  /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 `&lt;top (required)&gt;'
  /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 `&lt;main&gt;'
  Tasks: TOP =&gt; crawl_next
  </code></pre>
  
  <p>lib/tasks/scheduler.rake:</p>
  
  <pre><code>desc "perform crawls for active alerts if their interval has passed"
  task :crawl_next =&gt; :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) &lt; 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
  </code></pre>
  
  <p>crawl.rb model:</p>
  
  <pre><code>class Crawl &lt; 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 &gt; self.alert.response_time_threshold_ms
    end
  
    def errors
      self.resp_code != "200"
    end
  end
  </code></pre>
  
  <p>alert.rb model:</p>
  
  <pre><code>class Alert &lt; 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 =&gt; 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
  </code></pre>