Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning a parameter if that parameter is defined

I have abstracted out my models to be able to test multiple models at the same time. The issue is that some of the models have different parameters. Take this sample schema below.

Schemas (simplified)

# Table name: cars
#
#  id         :integer          not null, primary key
#  hp         :integer 
#  wheels     :integer 

# Table name: trucks
#
#  id         :integer          not null, primary key
#  hp         :integer 
#  wheels     :integer 

# Table name: boats
#
#  id         :integer          not null, primary key
#  motors     :integer
#  hp         :integer 

Test

setup do
   @models = ['cars', 'trucks', 'boats']
end

test 'something awesome' do
   @models.each do |model|
    # This works for cars and trucks, not for boats

    exemplar = FactoryGirl.create(model, id: 1, hp: 600, wheels: 4)

    # A bunch of assertions

  end
end

I can assign id and hp to all models but while cars and trucks have wheels, boats have motors. Is there a way to in the create call essentially say "If this method is defined, then use it, if not then ignore it"

What I would like to be able to do is call exemplar = FactoryGirl.create(model, id: 1, hp: 600, wheels: 4, motors: 2) and have it work across the board creating 3 objects:

  1. car: id = 1, hp = 600, wheels = 4
  2. truck: id = 1, hp = 600, wheels = 4
  3. boat: id = 1, hp = 600, motors = 2
like image 593
Zack Avatar asked Jul 30 '26 18:07

Zack


1 Answers

If you use rspec as a test framework,use shared examples in the current context.

This will allow you to build each object as you want, and have them all go through the same tests. Example:

groupe_example 'object' do
   it 'has a valid factory' do
     expect(object).to be_valid
   end
end

describe Car do
  let(:object){ create(:car_with_some_options) }
  include_examples 'object'
end

describe Truck do
  let(:object){ create(:truck_with_other_options) }
  include_examples 'object'
end

Otherwise, you should go for a solution like:

setup do
   @models = {:car => {hp: 600}, :truck => { wheels: 8, hp: 1000} }
end

test 'something awesome' do
   @models.each do |model, params|
    # This works for cars and trucks, not for boats

    exemplar = FactoryGirl.create(model, params)

    # A bunch of assertions

  end
end

which can be reformated better with different factories. For instance, if you create :default_car, :default_truck, etc factories for each of your model, you can then set whatever parameters you want there and then plain call them through FactoryGirl.create without having to worry about the parameters in your test.

================== EDIT ========================

If you really want to test whether the parameter is defined, you can either use attributes. A more comprehensive answer is here

Or, more simple, you can check whether there is a writer operator:

model.public_send(:wheels=, 4) if model.respond_to? :wheels=
like image 80
muichkine Avatar answered Aug 01 '26 09:08

muichkine



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!