Как я могу сгенерировать: attribute_for уже созданной Фабрики? - PullRequest
0 голосов
/ 11 сентября 2018

Обновление (не отвечайте)

Я только что узнал, что этот вопрос на самом деле не имеет смысла.Это было основано на моем собственном заблуждении о фабриках и о том, как они работают.


Вся идея была основана на неправильном представлении о том, как работает FactoryBot, в частности по какой-то причине я думал, что FactoryBot настраивает несколькопеременные, за которые фактически отвечал совершенно другой гем (Devise).

Есть ли простой способ получить доступ к «виртуальным атрибутам» для уже построенной фабрики?

Что-то вроде: attribute_for, ноиспользуется на экземпляре Фабрики вместо класса?

Так что вы можете сделать что-то вроде этого:

FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    password { "password" }
    password_confirmation { "password" }
  end
end

@user = FactoryBot.build(:user)

@user.factory_attributes # Not a real method
#-> { email: "name@gmail.com", password: "123456", password_confirmation: "123456" }

Почему я хочу это

Если вам интересно, я хочу, чтобы это было в состоянии сократить следующий код для спецификации запроса на вход в систему.

Отсюда:

let(:user_attributes) do
  FactoryBot.attributes_for(:user)
end

let(:user) do
  FactoryBot.create(:user, user_attributes)
end

# Triggers the create method in let(:user)
# Necessary to ensure the user exists in the database before testing sign in.
before { user } 

let(:user_params) do 
  { user: user_attributes }
end

it "redirects to the root path on successful sign in" do
  post user_session_path(params: user_params)
  expect(response).to redirect_to(root_path)
end

До этого:

let(:user) do
  FactoryBot.create(:user)
end

let(:user_params) do 
  { user: user.factory_attributes }
end

it "redirects to the root path on successful sign in" do
  post user_session_path(params: user_params)
  expect(response).to redirect_to(root_path)
end

Что значительно чище и менее запутанно, чем первое, особенно для начинающих разработчиков (можно было увидеть, что кто-то с небольшим опытом RSpec потратил довольно много времени, пытаясь выяснить, чтов аду строка "before {user}" делает)

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

Есть ли какой-нибудь простой способ получить доступ к «виртуальным атрибутам» для уже построенной фабрики?

Я думаю, вы не понимаете терминологию и / или как работает фабричный бот.Вы не строите фабрик .Фабрика уже существует и собирает пользователей (в данном случае).

После того, как пользователь построен / создан, он не знает, на какой фабрике он построен.И это правильно.Пользователи могут быть созданы разными способами.Если этот метод действительно существует, что вы ожидаете, что он вернется, когда вы создадите пользователя с User.create?

0 голосов
/ 11 сентября 2018

FactoryBot.build(:user) возвращает экземпляр модели ActiveRecord.Поэтому вы можете просто использовать ActiveRecord::Base#attributes, чтобы вернуть список атрибутов текущего объекта:

@user = FactoryBot.build(:user)
@user.attributes

Как только фабрика вернула экземпляр User, который user не имеетбольше информации о том, как это было инициализировано.Поэтому невозможно прочитать значения, которые не существуют в экземпляре.

Обходной путь может быть что-то вроде этого:

let(:parameters) do
  { user: FactoryBot.attributes_for(:user) }
end

before do
  FactoryBot.create(:user, parameters[:user])
end

it "redirects to the root path on successful sign in" do
  post user_session_path(params: parameters)
  expect(response).to redirect_to(root_path)
end

Но на самом деле, я думаю, вы должны быть более ясными о том, какие атрибуты вас действительно волнуют.Вы заботитесь об электронной почте и пароле пользователя - все остальные атрибуты не имеют отношения к данной спецификации.Поэтому я бы написал спецификацию так:

let(:email) { 'foobar@example.tld' }
let(:password) { 'secret' }

before do
  FactoryBot.create(:user, email: email, password: password, password_confirmation: password)
end

it "redirects to the root path on successful sign in" do
  post user_session_path(params: { user: { email: email, password: password } })
  expect(response).to redirect_to(root_path)
end
...