Anders Anders - 6 months ago 23
Ruby Question

Capybara + FactoryGirl, set relationship in form

I'm a newcomer when it comes to both

, In my Rails app I have a relationship that looks like this:

# App.rb
belong_to :plan

# Plan.rb
has_many :apps

Each app must have a plan, in my App.rb model I do it like this:
before_save :set_default_plan, on: :create

I want to test that app creation works, using Capybara integration tests. I currently have a test that looks like this:

require "rails_helper"

include Warden::Test::Helpers

describe "adding apps" do

let(:user) { FactoryGirl.create(:user) }
before { login_as(user, scope: :user) }

it "allows a user to create an app" do
visit apps_path
fill_in "App name", with: "My App"
click_on "create_app_button"
visit apps_path
expect(page).to have_content("My App")

After I create apps I render this in my view:
. If I run my tests with
bundle exec rspec
I currently get this error:

undefined method `free_requests' for nil:NilClass

In my app I also use FactoryGirl to test my models. I have the following (relevant) factories:

FactoryGirl.define do
factory :app do
name "Test"
association :plan, :factory => :plan

FactoryGirl.define do
factory :plan do
name "Default"

I wonder how I should set ut my factories and test suite to make this test become a green one.

Can I either assign a plan to the app I'm creating somehow with Capybara, or can I create a default association / plan for my app with FactoryGirl. Is is there another approach? Thankful for all assistance.


This is how my
method looks:

# App.rb
def set_default_plan
if self.new_record?
plan = Plan.find_by_stripe_id("default_plan")
if plan.nil? == false
self.plan = plan


FactoryGirl really shouldn't have anything to do with "apps" or "plans" in your test, since you're running through your controllers create action, unless set_default_plan doesn't actually create a plan if none exist. If that is the case then you could use FactoryGirl to create the required plan like - FactoryGirl.create(:plan) in your before block

You should also specify that the plan is a required association (this is default in Rails 5 so if you're using that this may not be necessary) which will prevent your Apps from being created without a plan.

# App.rb
belongs_to :plan, required: true

Another thing to note is you should always check for confirmation after clicking a button that performs an action before visiting another page. This is because the result of clicking the button is not guaranteed to be synchronous so visiting another page immediately can kill the action request.

click_on "create_app_button"
expect(page).to have_content("App Created!!!")  # whatever text is shown on success
visit apps_path