Factory Girl with enum and association
Asked Answered
L

2

2

I have a model that uses both an association and an enum attribute.

class ProjectItem < ActiveRecord::Base
  belongs_to :project

  enum status: {open: 0, pending: 1, completed: 2}

When I'm running a test on the create action of a model with an association, I use build(:model_name).attributes like this:

it "creates a new ProjectItem" do
  expect {
    post :create, document_project_item: build(:project_item).attributes
  }.to change(ProjectItem, :count).by(1)
end

This was failing, and I found this issue thread that explains why it doesn't work. Based on the comment, I was able to determine that on tables with an enum attribute but no association, things work with attributes_for(:model_name) as expected.

The issue thread doesn't seem to suggest a work around, though I'll admit I don't understand what 100% of what the FactoryGirl methods are doing behind the scenes. Here's the factory:

factory :project_item do
  project
  name { Faker::Company.bs }
  description { Faker::Lorem.paragraph }
  status :open
  due { Faker::Date.between(2.days.ago, 10.days.from_now) }
  sequence(:position) {|n| n }
  completed_at { Faker::Date.between(1.year.ago, Date.today) }
end

I tried putting an integer in status as well, but I get the same error:

 Failure/Error: post :create, project_item: build(:project_item).attributes
 ArgumentError:
   '0' is not a valid status
Lipscomb answered 22/12, 2014 at 16:12 Comment(2)
Have you inspected the value of status within the response of attributes_for or build(something).attributes? Also, try using pending instead of open and see if you get the same error with 1 instead of 0.Shuttlecock
When I run attributes_for from the console I get: {... :status=>:open, ...}, but it does not build a project to associate. When I run build(:project_item).attributes I get: {... "project_id"=>24,... "status"=>0, ...}. If I change 'status' to 'pending' or :pending, it does indeed give me the same error with 1 instead of 0. It looks like with Rails enums I wont be able to build forms in an intuitive way (with integer for value and string for the label), so it may be that enums are not going to make my life any easier at this point.Lipscomb
L
1

I'm open to other solutions, but this is what I came up with as a workaround.

let(:project_attributes) { build(:project_item).attributes.merge(status: 'pending') }
it "creates a new ProjectItem" do
  expect {
    post :create, project_id: project.id, project_item: project_attributes
  }.to change(ProjectItem, :count).by(1)
end
Lipscomb answered 23/12, 2014 at 20:44 Comment(0)
C
1

Having to add a .merge across pre-existing factory calls is a nightmare.

All you need in your factory is status 'open'

Catheterize answered 6/11, 2018 at 21:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.