0

I'm building a Rails application and I've encountered a really odd bug. The code [true false].sample is never supposed to return blank. However, it sometimes does so when running rake db:seed.

In my application I have a Store model that has presence validations:

class Store < ActiveRecord::Base
  validates_presence_of :accepts_credit, :parking
end

I also run a test in rspec like this (that always passes)

require 'rails_helper'

RSpec.describe Store, type: :model do 
  it { should validate_presence_of :accepts_credit }  
  it { should validate_presence_of :parking        }  
end

Now, in my seeds file I have

Store.create(
  ...
  accepts_credit: [false, true].sample(1),
  parking:      %w[lots some none].sample(1),
  ... 
)

Running this in the terminal with rake db:reset --trace, I get errors that the store wasn't created. I inspected this by running Store.create! instead of Store.create which causes the terminal to display errors.Validation failed: Accepts credit can't be blank.

Now, I'm relatively new to Rails but I don't understand why the sample method .sample could return blank. According to the docs: http://ruby-doc.org/core-2.2.0/Array.html#method-i-sample, sample always returns an element from the array.

Edit

I've used .sample in replace of .sample(1) as well.

What am I missing? Is .blank doing what I think it is?

user3162553
  • 2,699
  • 3
  • 37
  • 61

2 Answers2

0

false.blank? is true (i.e. not "present"), so you'll need to rewrite your validation if you want to persist false values. You might try validates_inclusion_of :accepts_credit, in: [true, false] if you want to protect against nil.

Ben
  • 2,096
  • 15
  • 9
  • Ok, this makes sense and was my first intuition but the shoulda-matchers docs said that you shouldn't use inclusion on booleans. Here's the link to the docs: https://github.com/thoughtbot/shoulda-matchers/blob/master/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb. – user3162553 Oct 10 '15 at 23:44
  • On second thought, I guess that answers the question. You shouldn't validate presence of booleans because AR will typecast them in. Your answer makes since on understanding what AR is doing. Thanks! – user3162553 Oct 10 '15 at 23:45
  • AR will typecast values once records have been pulled from the DB, so `Store.last.accepts_credit?` will work as expected regardless of the inclusion validation. Nonetheless, it could be important to ensure you don't have `NULL` values in boolean fields because queries like `Store.where(accepts_credit: false)` will not return such records. `FALSE` != `NULL` in the DB. – Ben Oct 11 '15 at 06:14
  • 1
    More info here: http://stackoverflow.com/questions/5170008/rails-validating-inclusion-of-a-boolean-fails-tests/10942223#10942223 – Ben Oct 11 '15 at 06:16
  • Thanks a lot. That's a great explanation! – user3162553 Oct 11 '15 at 07:10
0

I think you may have forgot to run migrations. I think you were supposed to run: rake db:migrate:reset

Try to run, rake db:migrate, and then, rake db:seed. I apologize ahead of time if this answer does not help.

  • It is my understanding that `rake db:reset` drops the database, creates it, and runs all migrations in order then seeds it. – user3162553 Oct 10 '15 at 23:46