Factory Girl关联对象实例化[使用设计]

时间:2016-02-01 15:06:45

标签: ruby-on-rails devise associations factory-bot

我有三个模型用户(作者),它包含设计逻辑:

的应用程序/模型/ user.rb

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :questions
  has_many :answers
end

问题:

的应用程序/模型/ question.rb

# Model for Question
class Question < ActiveRecord::Base
  has_many :answers, dependent: :destroy
  belongs_to :author, class_name: 'User', foreign_key: 'user_id'

  validates :title, presence: true, length: { maximum: 100 }
  validates :body, presence: true, length: { minimum: 10 }
  validates :author, presence: true
end

并回答:

的应用程序/模型/ answer.rb

# Model for Answer
class Answer < ActiveRecord::Base
  belongs_to :question
  belongs_to :author, class_name: 'User', foreign_key: 'user_id'

  validates :body, presence: true, length: { minimum: 10 }
  validates :question_id, presence: true
  validates :author, presence: true
end

和他们的工厂:

规格/工厂/ users.rb的

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

  sequence :password do |n|
    "testpassword#{n}"
  end

  factory :user, aliases: [:author] do
    email
    # tried sequence generator and fixed password - both have no impact on result
    # password '1234567890'
    # password_confirmation '1234567890'
    password
  end

end

规格/工厂/ answers.rb

FactoryGirl.define do
  factory :answer do
    body 'Answer Body'
    author
    question
  end

  factory :nil_answer, class: 'Answer' do
    question
    body nil
  end
end

规格/工厂/ questions.rb

FactoryGirl.define do
  factory :question do
    title 'Question Title'
    body 'Question Body'
    author

    factory :question_with_answers  do
      after(:create) do |question|
        # changing create_list to create has no impact on result
        # create_list(:answer, 2, question: question)
        create(:answer, question: question)
      end
    end
  end
end

测试代码:

规格/特征/ delete_answer_spec.rb

require 'rails_helper'

feature 'Delete answer', %q{
  By some reason
  As an authenticated user
  I want to delete answer
} do

  given(:question) { create(:question_with_answers) }
  given(:user) { create(:user) }
  given(:ans) { create(:answer) }

  scenario 'Answer author password should not be nil' do
    expect(question.answers.first.author.password).to_not be_nil
    # question.author.password and ans.author.password return not nil
    # I need password to do:
    # visit new_user_session_path
    # fill_in 'Email', with: user.email
    # fill_in 'Password', with: user.password
    # click_on 'Log in'
  end 
end

任何人都可以解释为什么以下给出的陈述:

given(:question) { create(:question_with_answers) }

创建问题对象:

question.author.password #=> '1234567890'

但:

question.answers.first.author.password #=> nil

为什么方法&#34;创建&#34;正确地实例化问题的作者(设置字段密码),但是&#34; create_list&#34;在&#34;之后&#34;回调是否使用nil字段创建作者?

rails 4.2.5,ruby 2.3.0,设计3.5.6,看守1.2.6,factory_girls_rails 4.6.0(4.5.0)

1 个答案:

答案 0 :(得分:3)

Devise(和大多数身份验证库)加密密码,不允许您从数据库中检索的模型访问密码。密码可以通过内存中的读取器方法暂时可用,但如果从数据库中检索记录,则无法使用该密码。

如果你这样做:

user = User.new(password: "example")
p user.password

我猜你会看到"example"

但如果你这样做:

user = User.first
p user.password

我打赌你会看到nil(假设你的数据库中有用户记录)。

当您查询像question.answers.first.author这样的关联代理时,它会再次访问数据库以找到答案和作者。这意味着您正在使用不再具有密码的其他实例。