validation error through FactoryGirl

2019-09-05 02:27发布

问题:

I have problems on validating my data through FactoryGirl.

For team.rb, the custom validations are has_only_one_leader and belongs_to_same_department

class Team < ActiveRecord::Base
    attr_accessible :name, :department, :active

    has_many :memberships
    has_many :users, through: :memberships

    accepts_nested_attributes_for :memberships, :users

    validates :department, inclusion: [nil, "Architectural", "Interior Design"]
    validates_uniqueness_of :name, scope: :department, conditions: -> { where(active: true) }
    validate :has_only_one_leader
    validate :belongs_to_same_department

    def has_only_one_leader
        unless self.users.where!(designation: "Team Leader").size == 1
            errors.add(:team, "needs to have exactly one leader")
        end
    end

    def belongs_to_same_department
        unless self.users.where!.not(department: self.department).size == 0
            errors.add(:users, "should belong to the same department")
    end
end

I'll also include membership.rb and user.rb (associations only) just for reference.

class Membership < ActiveRecord::Base
    belongs_to :team
    belongs_to :user
end

class User < ActiveRecord::Base
    has_many :memberships
    has_many :teams, through: :memberships
end

Here's my factory for team.rb

FactoryGirl.define do
    factory :team do
        sequence(:name) {|n| "Team #{n}" }
        department "Architectural"

        before(:create) do |team|
            team.users << FactoryGirl.create(:user, designation: "Team Leader",
                department: "Architectural")
            team.users << FactoryGirl.create_list(:user, 5, 
                designation: "CAD Operator", department: "Architectural")
        end
    end
end

It seems that after I do FactoryGirl.create(:team) in the rails console, it seems that I got the error messages from my validations.

Two things I've noticed when I manually build a team, specifically adding members to the team with 1 leader and 5 members belonging to the same department:

  1. team.users.where!(designation: "Team Leader").size returns 6 although there's only one leader, same goes for changing the designation to CAD Operator, returns 6 although there are only five non leaders in the team.

  2. same goes for checking if the members are in the same department, team.users.where!.not(department: team.department).size returns 6, although all of them belong to the same department.

Are there any modifications to make in my model or in my factory?

回答1:

Here are the things that I've discovered before getting the answer.

  1. team.users.where(designation: "Team Leader") returns a User::ActiveRelation_AssociationRelation object
  2. team.users returns a User::ActiveRecord_Associations_CollectionProxy object
  3. CollectionProxy has no method where since the this method (in my opinion) is a query to the database (with exception if the team is already saved in the database, you can use where, but in this case, it's only for building)

Therefore, I used the select method accompanied with the count, to return the correct values like so. I'll use my example from the question to illustrate the answer.

  1. team.users.select(:designation) {|user| user.designation == "Team Leader"}.count returns 1
  2. team.users.select(:department) {|user| user.department != team.department}.count returns 0