ruby-on-rails - sheet - factory bot rails tutorial
¿Cómo puedo restablecer una secuencia factory_girl? (8)
Hola a todos, Después de rastrear mi camino a través del código fuente, finalmente he encontrado una solución para esto. Si estás usando factory_girl 1.3.2 (que fue la última versión en el momento en que escribo esto), puedes agregar el siguiente código al principio de tu archivo de factories.rb:
class Factory
def self.reset_sequences
Factory.factories.each do |name, factory|
factory.sequences.each do |name, sequence|
sequence.reset
end
end
end
def sequences
@sequences
end
def sequence(name, &block)
s = Sequence.new(&block)
@sequences ||= {}
@sequences[name] = s
add_attribute(name) { s.next }
end
def reset_sequence(name)
@sequences[name].reset
end
class Sequence
def reset
@value = 0
end
end
end
Luego, en el env.rb de Cucumber, simplemente agregue:
After do
Factory.reset_sequences
end
Supongo que si encuentra el mismo problema en sus pruebas de rspec, podría usar rspecs después de: cada método.
En este momento, este enfoque solo toma en consideración las secuencias definidas dentro de una fábrica, tales como:
Factory.define :specialty do |f|
f.sequence(:title) { |n| "Test Specialty #{n}"}
f.sequence(:permalink) { |n| "permalink#{n}" }
end
Todavía no he escrito el código para manejar: Factory.sequence ...
Espero que esto ayude a todas las demás personas frustradas que no pueden entender por qué en el mundo la chica de la fábrica ya no proporciona esto. Tal vez voy a bifurcar el proyecto github y enviar una solicitud de extracción con esta solución, ya que no cambia ninguna de sus funciones internas.
-Andrés
Siempre que tenga una fábrica de proyectos.
Factory.define :project do |p|
p.sequence(:title) { |n| "project #{n} title" }
p.sequence(:subtitle) { |n| "project #{n} subtitle" }
p.sequence(:image) { |n| "../images/content/projects/#{n}.jpg" }
p.sequence(:date) { |n| n.weeks.ago.to_date }
end
Y que estoy creando instancias de proyecto.
Factory.build :project
Factory.build :project
Para este momento, la próxima vez que ejecute Factory.build (: project) recibiré una instancia de Project con un título establecido en "project 3 title" y así sucesivamente. No es sorprendente.
Ahora diga que deseo restablecer mi contador dentro de este alcance. Algo como:
Factory.build :project #=> Project 3
Factory.reset :project #=> project factory counter gets reseted
Factory.build :project #=> A new instance of project 1
¿Cuál sería la mejor manera de lograr esto?
Actualmente estoy usando las siguientes versiones:
factory_girl (1.3.1) factory_girl_rails (1.0)
Gracias de antemano Saludos cordiales.
No hay una forma integrada de restablecer una secuencia, consulte el código fuente aquí:
http://github.com/thoughtbot/factory_girl/blob/master/lib/factory_girl/sequence.rb
Sin embargo, algunas personas han hackeado / parchado esta característica. Aquí hay un ejemplo:
http://www.pmamediagroup.com/2009/05/smarter-sequencing-in-factory-girl/
Para restablecer una secuencia particular puedes probar
# spec/factories/schedule_positions.rb
FactoryGirl.define do
sequence :position do |n|
n
end
factory :schedule_position do
position
position_date Date.today
...
end
end
# spec/models/schedule_position.rb
require ''spec_helper''
describe SchedulePosition do
describe "Reposition" do
before(:each) do
nullify_position
FactoryGirl.create_list(:schedule_position, 10)
end
end
protected
def nullify_position
position = FactoryGirl.sequences.find(:position)
position.instance_variable_set :@value, FactoryGirl::Sequence::EnumeratorAdapter.new(1)
end
end
Para usuarios de Google: sin ampliar aún más, simplemente haga FactoryGirl.reload
FactoryGirl.create :user
#=> User id: 1, name: "user_1"
FactoryGirl.create :user
#=> User id: 2, name: "user_2"
DatabaseCleaner.clean_with :truncation #wiping out database with truncation
FactoryGirl.reload
FactoryGirl.create :user
#=> User id: 1, name: "user_1"
trabaja para mí en
* factory_girl (4.3.0)
* factory_girl_rails (4.3.0)
https://.com/a/16048658
Según ThoughBot Here , la necesidad de restablecer la secuencia entre las pruebas es un antipatrón.
Para veranear :
Si tienes algo como esto:
FactoryGirl.define do
factory :category do
sequence(:name) {|n| "Category #{n}" }
end
end
Tus pruebas deberían verse así:
Scenario: Create a post under a category
Given a category exists with a name of "Category 1"
And I am signed in as an admin
When I go to create a new post
And I select "Category 1" from "Categories"
And I press "Create"
And I go to view all posts
Then I should see a post with the category "Category 1"
No esta:
Scenario: Create a post under a category
Given a category exists
And I am signed in as an admin
When I go to create a new post
And I select "Category 1" from "Categories"
And I press "Create"
And I go to view all posts
Then I should see a post with the category "Category 1"
Si está utilizando Pepino, puede agregar esto a una definición de paso:
Given(/^I reload FactoryGirl/) do
FactoryGirl.reload
end
Entonces solo llámalo cuando sea necesario.
Simplemente llame a FactoryGirl.reload en su devolución de llamada antes / después. Esto se define en el código base de FactoryGirl como:
module FactoryGirl
def self.reload
self.factories.clear
self.sequences.clear
self.traits.clear
self.find_definitions
end
end
Llamar a FactoryGirl.sequences.clear no es suficiente por alguna razón. Hacer una recarga completa puede tener algo de sobrecarga, pero cuando lo intenté con / sin la devolución de llamada, mis pruebas tardaron alrededor de 30 segundos en ejecutarse de cualquier manera. Por lo tanto, la sobrecarga no es suficiente para afectar mi flujo de trabajo.
Tenía que asegurar que las secuencias van del 1 al 8 y reiniciar a 1 y así sucesivamente. Implementado de esta manera:
class FGCustomSequence
def initialize(max)
@marker, @max = 1, max
end
def next
@marker = (@marker >= @max ? 1 : (@marker + 1))
end
def peek
@marker.to_s
end
end
FactoryGirl.define do
factory :image do
sequence(:picture, FGCustomSequence.new(8)) { |n| "image#{n.to_s}.png" }
end
end
El doc dice: "El valor solo necesita admitir el método #next
". Pero para que el objeto CustomSequence siga funcionando, también debe admitir el método #peek
. Por último, no sé por cuánto tiempo funcionará esto, ya que se piratea en las partes internas de FactoryGirl. Cuando hacen un cambio, esto puede no funcionar correctamente.