2012-05-02 14 views
5

¡Nuevo en RSpec y Factory Girl, y perdiendo esta batalla!prueba has_many through con validación usando RSpc 2.9.0 + FactoryGirl 3.2

Tengo una tabla de combinación MealItems que tiene validación en una de sus propiedades. En la consola de rieles que puedo hacer con éxito el siguiente:

meal = Meal.create!(...) 
food = Food.create!(...) 
item1 = MealItem.create!(meal, food, 1234) # 1234 being the property that is required 

puedo entonces automagicamente consigo una gran variedad de alimentos en una comida dada a través de la MealItem así:

meal.foods 

El problema es que no puedo averiguar cómo crear fábricas de forma adecuada, de modo que esta relación esté disponible en la especificación. Puedo asignar los artículos a una comida, y poner a prueba esos, pero no puedo conseguir el has_many través de la relación de trabajo (meal.foods)

Modelos

class Meal < ActiveRecord::Base 

    has_many :meal_items 
    has_many :foods, :through => :meal_items 

end 

class MealItem < ActiveRecord::Base 

    belongs_to :meal 
    belongs_to :food 

    validates_numericality_of :serving_size, :presence => true, 
              :greater_than => 0 
end 

class Food < ActiveRecord::Base 

    has_many :meal_items 
    has_many :meals, :through => :meal_items 

end 

spec/factories.rb

FactoryGirl.define do 

    factory :lunch, class: Meal do 
    name  "Lunch" 
    eaten_at Time.now 
    end 

    factory :chicken, class: Food do 
    name   "Western Family Bonless Chicken Breast" 
    serving_size 100 
    calories  100 
    fat    2.5 
    carbohydrates 0 
    protein   19 
    end 

    factory :cheese, class: Food do 
    name   "Armstrong Light Cheddar" 
    serving_size 30 
    calories  90 
    fat    6 
    carbohydrates 0 
    protein   8 
    end 

factory :bread, class: Food do 
    name   "'The Big 16' Multigrain Bread" 
    serving_size 38 
    calories  100 
    fat    1 
    carbohydrates 17 
    protein   6 
    end 

    factory :item1, class: MealItem do 
    serving_size  100 
    association  :meal, factory: :lunch 
    association  :food, factory: :chicken 
    end 

    factory :item2, class: MealItem do 
     serving_size  15 
     association  :meal, factory: :lunch 
     association  :food, factory: :cheese 
    end 

    factory :item3, class: MealItem do 
    serving_size  76 
    association  :food, factory: :bread 
    association  :meal, factory: :lunch 
    end  


    factory :meal_with_foods, :parent => :lunch do |lunch| 
    lunch.meal_items { |food| [ food.association(:item1), 
          food.association(:item2), 
          food.association(:item3) 
          ]} 


    end 
end 

especificación/modelos/meal_spec.rb

... 

describe "Nutritional Information" do 

before(:each) do 

    #@lunch = FactoryGirl.create(:meal_with_foods) 

    @item1 = FactoryGirl.create(:item1) 
    @item2 = FactoryGirl.create(:item2) 
    @item3 = FactoryGirl.create(:item3) 
    @meal = FactoryGirl.create(:lunch) 

    @meal.meal_items << @item1 
    @meal.meal_items << @item2 
    @meal.meal_items << @item3 

    @total_cals = BigDecimal('345') 
    @total_fat = BigDecimal('7.5') 
    @total_carbs = BigDecimal('34') 
    @total_protein = BigDecimal('35') 

end 

# Would really like to have 
#it "should have the right foods through meal_items" do 
    #@meal.foods[0].should == @item1.food 
#end 

it "should have the right foods through meal_items" do 
    @meal.meal_items[0].food.should == @item1.food 
end 


it "should have the right amount of calories" do 
    @meal.calories.should == @total_cals 
end 

... 

Mi pregunta es:

¿Cómo puedo configurar estas fábricas para que pueda hacer referencia a Meal.foods en mis pruebas ya que no puedo asignar los alimentos directamente a una comida debido al requisito de validación en la tabla de unión. ¿No estoy escribiendo correctamente las fábricas MealItem en el DB durante la prueba, y es por eso que la relación has_many through no existe en mi especificación?

Cualquier ayuda es muy apreciada.

Respuesta

0

Sí, necesita una fábrica para MealItem, y necesita usar esa fábrica en la especificación para poder pasar la validación. Si no tiene ningún campo requerido que no sean las dos claves externas, probablemente ya funcione. Así que después de la creación de la fábrica con un tamaño servering por defecto, debería reemplazar esto:

@meal.meal_items << @item1 
@meal.meal_items << @item2 
@meal.meal_items << @item3 

con esto:

FactoryGirl.create(:meal_item, :meal => @meal, :item => @item1) 
FactoryGirl.create(:meal_item, :meal => @meal, :item => @item1) 
FactoryGirl.create(:meal_item, :meal => @meal, :item => @item1) 

Una alternativa sería la de establecer un valor predeterminado tamaño de la porción en su modelo. Eso le permitiría dejar sus pruebas como estaban, y puede hacer que sea más fácil usar su sintaxis preferida en su código real también.

Cuestiones relacionadas