Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Should factory_girl bypass :attr_accessible by default?
# factory_girl has difficulty playing nicely with attr_accessible.
class Article
belongs_to :owner
attr_accessible :name
Factory.define(:article) do |a|
a.association :owner
a.sequence(:name) {|i| "Article #{i}"}
# A core problem is that attr_accessible denies factory_girl's assignment of those specific attributes.
# It forces us as consumers of the Factory to use the :build strategy and then manually assign those
# attributes which is long-winded and annoying to say the least.
@article =
@article.owner = Factory(:owner)
# Anyone who's used attr_accessible before will recognize a similar pattern in their controllers.
def create
@article =[:article])
@article.owner = admin? ? User.find(params[:article][:owner_id]) : current_user
# For the controller case, we can leverage Ryan Bates' trusted-params plugin.
def create
params[:article].trust(:owner_id) if admin?
@article =[:article])
# However, we're still left out to dry if we want to use factory_girl for our functional tests.
# My current solution is to define two separate factories to properly test both an admin and a regular
# user creating an article.
Factory.define(:attrs_for_article, :default_strategy => :attributes_for, :class => 'Article') do |a|
a.sequence(:name) {|i| "Article #{i}"}
# When used in conjunction with the trusted-params snippet, this works as intended.
Factory.define(:article, :parent => :attrs_for_article) do |a|
a.association :owner
# So great, now I can do my functional tests. But what about my unit tests?
Factory(:article) # ==> error that owner is not set!! FUCK!
# Grrrr. So how can I get trusted-params-like functionality in my models/unit tests?
# One way that factory_girl could solve this would be to support a before_save callback, e.g.
Factory.define(:article, :parent => :attrs_for_article) do |a|
a.before_save {|article| article.owner ||= Factory(:owner) }
# Another option would be to bake in a :bypass_attr_accessible option for factories, e.g.
Factory(:article, :bypass_attr_accessible)
# But even this has its shortcomings. Now I as a consumer of the Article factory must remember that it's
# protected some attributes (which I'm not even passing in because they're part of the default factory
# definition).
# Perhaps a better solution is to add it as an option to the factory definition?
Factory.define(:article, :attr_accessible => :bypass) do |a|
a.association :owner
a.sequence(:name) {|i| "Article #{i}"}
# What is nice about this is we can very easily test our authorization in our functional tests.
def test_should_update_article_as_a_regular_user
@user = Factory(:user)
@name = 'Something now in the factory'
@article = Factory(:article, :name => @name, :owner => @user)
log_in @user
# keep in mind the article factory will create a brand new user!
put :update, :id =>, :article => Factory.attributes_for(:article)
assert_equal @article.reload.owner, @current_user
assert_not_equal, @name
# Or better yet, should factory_girl just bypass attr_accessible by default?

webandy commented Dec 9, 2010

Hi John. What did you end up doing to use factory_girl and attr_accessible together? (rails 2.3.5, factory_girl 1.3.2)


jtrupiano commented Dec 9, 2010

Hey Andy, honestly I don't remember. I actually have a sneaking suspicion that this gist is inaccurate...that attr_accessible was not giving me problems.

goat000 commented Mar 15, 2012

attr_accessible does seem to be causing the problems in my use of factory_girl for the record... so I wouldn't be surprised if it was your problem, too.

goat000 commented Mar 16, 2012

Also, for the poor soul who googled your way here 3 years in the future, it looks like factory_girl callbacks have since solved this, in a manner similar to the before_save suggestion above:

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