Factory Girl 关联对象实例化[使用设计]
Factory Girl associated object instantiation [using devise]
我有三个模型用户(作者),其中包含设计逻辑:
app/models/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
问题:
app/models/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
并回答:
app/models/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
和他们的工厂:
spec/factories/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
spec/factories/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
spec/factories/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
测试代码:
spec/features/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
为什么方法 "create" 正确地实例化了问题的作者(设置了字段密码),但是 "create_list" 在 "after" 回调中创建了作者作为答案,没有字段?
rails4.2.5,ruby2.3.0,设计3.5.6,典狱长1.2.6,factory_girls_rails4.6.0(4.5.0)
设计(和大多数身份验证库)加密密码,不允许您访问从数据库检索的模型中的密码。密码可能通过内存中的方法暂时可用 reader,但如果您从数据库中检索记录,则密码将不可用。
如果你这样做:
user = User.new(password: "example")
p user.password
我猜你会看到 "example"
。
但如果你这样做:
user = User.first
p user.password
我打赌你会看到 nil
(假设你的数据库中有用户记录)。
当你查询像question.answers.first.author
这样的关联代理时,它会再次进入数据库寻找答案和作者。这意味着您正在使用另一个实例,该实例不再有可用的密码。
我有三个模型用户(作者),其中包含设计逻辑:
app/models/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
问题:
app/models/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
并回答:
app/models/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
和他们的工厂:
spec/factories/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
spec/factories/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
spec/factories/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
测试代码:
spec/features/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
为什么方法 "create" 正确地实例化了问题的作者(设置了字段密码),但是 "create_list" 在 "after" 回调中创建了作者作为答案,没有字段?
rails4.2.5,ruby2.3.0,设计3.5.6,典狱长1.2.6,factory_girls_rails4.6.0(4.5.0)
设计(和大多数身份验证库)加密密码,不允许您访问从数据库检索的模型中的密码。密码可能通过内存中的方法暂时可用 reader,但如果您从数据库中检索记录,则密码将不可用。
如果你这样做:
user = User.new(password: "example")
p user.password
我猜你会看到 "example"
。
但如果你这样做:
user = User.first
p user.password
我打赌你会看到 nil
(假设你的数据库中有用户记录)。
当你查询像question.answers.first.author
这样的关联代理时,它会再次进入数据库寻找答案和作者。这意味着您正在使用另一个实例,该实例不再有可用的密码。