设置FactoryGirl和与Rspec的关联混乱

时间:2013-09-08 01:02:32

标签: ruby-on-rails rspec tdd factory-bot rspec-rails

我对学习TDD相当陌生,并且在这方面取得了成功。

以下是我的工厂(到目前为止):

FactoryGirl.define do
  sequence(:email) do |n|
    "user#{n}@example.com"
  end

  factory :user do
    email
    first_name Faker::Name.first_name
    last_name Faker::Name.last_name
    password "password"
    password_confirmation "password"
    agreed_to_age_requirements true
    username "testing123"
    state "AL"
    city_id 201
    school_id 20935
    handedness "Left"

    subscriptions {[create(:subscription)]}
    roles {[create(:role)]}
  end

  factory :athlete, class: "Athlete", parent: :user do
    type "Athlete"
    recruit_year "2016"
  end
end

FactoryGirl.define do
  factory :subscription do
    trial_expiry 30.days.from_now
    active true

    account_type {create(:account_type, name: "Free", price: 0)}
  end
end

FactoryGirl.define do
  factory :role do
    name "Subscription Admin"
  end
end

这是我的规范文件:

require 'spec_helper'

describe School do

  describe "associations" do
    it { should belong_to(:city) }
    it { should have_many(:users) }
    it { should have_many(:athletes) }
  end

  describe "validations" do
    it { should validate_presence_of(:name) }
    it { should validate_presence_of(:state) }
  end

  describe "scopes" do
    before(:each) do
      @school = create(:school, city_id: 1)
    end

    it "returns a school with the given city id" do
      School.in_city(1).should include(@school)
    end

    it "excludes schools that are not in the given city" do
      School.in_city(2).should_not include(@school)
    end
  end

  describe "instance methods" do
    let(:other_school) { create(:school, name: "Football High", state: "GA") }
    let(:athlete) { create(:athlete, school: other_school) }

    describe "#generate_custom_slug" do
      it "should return parameterized model" do
        other_school.generate_custom_slug.should eq("#{other_school.state.downcase} #{other_school.name.parameterize}")
      end
    end

    describe "#all_athletes" do

      context "when no parameters are passed in" do
        it "should return an array of athletes that belong to school" do
          other_school.all_athletes.should include(athlete)
        end
      end

      context "when given a sport name" do
        it "should return an array of athletes with the given sport name that belong to the school" do)
          other_school.all_athletes("football").should include(athlete)
        end
      end
    end
  end
end

我在哪里"卡住" at正在测试我的上一个context。用户通过user_sports进行了许多运动,当您访问/schools/1/football时,应该通过all_athletes实例方法返回属于该学校的所有运动员的列表。我对如何使用FactoryGirl

进行设置感到困惑

供参考,这是我的学校模型:

class School < ActiveRecord::Base
  extend FriendlyId
  friendly_id :generate_custom_slug, use: :slugged

  belongs_to :city
  has_many :users
  has_many :athletes

  validates_presence_of :name, :state

  default_scope order: 'name ASC'

  scope :in_city, ->(city_id) { where city_id: city_id }

  def titleized_name
    self.name.titleize
  end

  def generate_custom_slug
    # only generate a slug if the state and name are present
    # if they aren't present, validations fail
    "#{state.downcase} #{name.downcase.parameterize}" if state.present? && name.present?
  end

  def all_athletes(sport_name = nil, recruit_year = nil)
    return athletes if sport_name.nil? && recruit_year.nil?
    results = athletes.select { |athlete| !(athlete.sports & Sport.by_name_label(sport_name)).empty? } unless sport_name.nil?
    results = results.select { |athlete| athlete.recruit_year.eql?(recruit_year.to_i) } unless recruit_year.nil?

    results
  end
end

1 个答案:

答案 0 :(得分:2)

在这种情况下,除非运动员和学校很难设置,否则你可能完全避免使用FactoryGirl。创建一所学校,并在每次测试中添加一名运动员(或运动员)。如果你想让它变得更加复杂,那么请稍后再去FactoryGirl。