Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get FactoryGirl model attributes with has_and_belongs_to_many association?

I'm trying to get FactoryGirl.attributes_for(:trip) with HABTM association :countries because controller test fails - :countries absent in :trip attributes):

TripsController:

class TripsController < ApplicationController
  def create
    trip = Trip.new(create_params)
    if trip.save
      redirect_to trips_path, notice: 'Trip successfully created.'
    else
      redirect_to :back, alert: trip.errors.full_messages.join('<br>').html_safe
    end
  end

  def create_params
    params.require(:trip).permit(:end_date, :description, country_ids: [], countries: [])
  end
end

RSpec TripsController test:

describe TripsController do
  describe 'POST #create' do
    before { post :create, trip: attributes_for(:trip) }
    it { is_expected.to redirect_to trips_path }
  end
end

Trip model:

class Trip < ActiveRecord::Base
  # Associations
  has_and_belongs_to_many :countries

  #Validations
  validate :require_at_least_one_country

  private

  def require_at_least_one_country
    if country_ids.empty? && countries.count == 0
      errors.add(:base, 'Please select at least one country')
    end
  end
end

Trip factory:

FactoryGirl.define do
  factory :trip do
    description  { Faker::Lorem.sentence }
    end_date  { DateTime.now + 1.day }

    after(:build) do |trip, evaluator|
      trip.countries << FactoryGirl.create(:country, :with_currencies)
    end
  end
end

Gemfile:

factory_girl_rails (4.5.0)

Tried this: http://makandracards.com/jan0sch/11111-rails-factorygirl-and-has_and_belongs_to_many, but useless.

like image 463
Andrew Zelenets Avatar asked Feb 02 '26 03:02

Andrew Zelenets


1 Answers

Here is the answer with the explanation:

FactoryGirl.define do
  factory :trip do
    description  { Faker::Lorem.sentence }
    end_date  { DateTime.now + 1.day }

    after(:build) do |trip, evaluator|
      trip.countries << FactoryGirl.create(:country, :with_currencies)
    end
  end
end

FactoryGirl.attributes_for(:trip) returns

{
  :description=>"Eum alias tenetur odit voluptatibus inventore qui nobis.",
  :end_date=>Wed, 16 Sep 2015 11:48:28 +0300
}

.

FactoryGirl.define do
  factory :trip do
    description  { Faker::Lorem.sentence }
    end_date  { DateTime.now + 1.day }
    country_ids { [FactoryGirl.create(:country, :with_currencies).id] }
  end
end

FactoryGirl.attributes_for(:trip) returns

{
  :description=>"Assumenda sapiente pariatur facilis et architecto in.", 
  :end_date=>Wed, 16 Sep 2015 11:45:22 +0300,
  :country_ids=>[4]
}
like image 55
Andrew Zelenets Avatar answered Feb 04 '26 19:02

Andrew Zelenets