New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build & build_stubbed skip "before_validation" calls? #483

Closed
brycesenz opened this Issue Jan 31, 2013 · 5 comments

Comments

Projects
None yet
3 participants
@brycesenz
Copy link

brycesenz commented Jan 31, 2013

I am using FactoryGirl to test a model that is being extended with a Concern. A simplified version is below:

module SampleConcern
  extend ActiveSupport::Concern

  included do
    include ActiveModel::Validations
  end

  module ClassMethods
    def has_before_validations
      before_validation :strip_username_whitespace
      before_validation :strip_email_whitespace
    end
  end
  ...
end

class SampleUser < ActiveRecord::Base
  include ActiveModel::Validations
  include SampleConcern
  has_before_validations

  attr_accessible :username, :email
  ...
end

If I create a SampleUser with factory girl create, then the before_validation hooks in the concern are run. If I use 'build' or 'build_stubbed' though, then my before_validation hooks are somehow being skipped. Is that desired behavior? I couldn't find it in the documentation.

@joshuaclayton

This comment has been minimized.

Copy link
Member

joshuaclayton commented Feb 1, 2013

Hey @brycesenz, it doesn't call the before_validation callbacks on the model because FactoryGirl doesn't call #valid? on the model after it builds it. Here's the doc explaining how FG plays with ActiveRecord; basically when you call build or build_stubbed, it's just instantiating the object and stopping (so, no #save!, no #valid?, etc.)

To have the before_validation callbacks run, you'll need to check validity or save and then assert that whitespace is removed. Hope that clears things up!

@brycesenz

This comment has been minimized.

Copy link
Author

brycesenz commented Feb 1, 2013

Ah, ok, that makes sense. I'd seen somewhere around StackOverflow that build performs validations, but I suppose that was wrong. Thanks for clearing up the misconception.

@joshuaclayton

This comment has been minimized.

Copy link
Member

joshuaclayton commented Feb 1, 2013

You're welcome! If you're using later versions of FG (4.1 will definitely work) you could use callbacks and traits to do something like this:

FactoryGirl.define do
  trait :validated do
    after(:build) do |object|
      object.valid?
    end
  end

  factory :user do
    # user attributes
  end
end

user = build(:user, :validated, username: '   zomg whitespace!!!    ') # instantiates User, sets attributes, calls #valid?
expect(user.username).to eq 'zomg whitespace!!!'
@joshuaclayton

This comment has been minimized.

Copy link
Member

joshuaclayton commented Feb 1, 2013

To clarify, if you're explicitly testing your before_validation callbacks, you should probably just call #valid? on the instance manually (since it's a lot more explicit as to what's going on instead of hiding it in a trait), but I just wanted to demonstrate that you could technically achieve a validated object with FG. Hope this helps!

@quinHD

This comment has been minimized.

Copy link

quinHD commented Mar 14, 2016

Thanks joshuaclayton! Your explanation is great. It was very useful for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment