has_many при уважении стратегии сборки в factory_girl

Продолжение ryan_s тема предварительно созданных карт и быстро случайного поиска: вместо вектора мы можем использовать параллельную карту итераторов, которые должны ускорить случайный поиск немного.

map<K, V> const original;
...

// construct index-keyed lookup map   
map<unsigned, map<K, V>::const_iterator> fast_random_lookup;
map<K, V>::const_iterator it = original.begin(), itEnd = original.end();
for (unsigned i = 0; it != itEnd; ++it, ++i) {
  fast_random_lookup[i] = it;
}

// lookup random value
V v = *fast_random_lookup[random_0_to_n(original.size())];
20
задан tfwright 24 January 2010 в 21:51
поделиться

2 ответа

Я написал правильно с наследованием и всем остальным. Мои коммиты объединены в здесь и здесь .

Теперь это в FactoryGirl 1.2.3, woot!

18
ответ дан 30 November 2019 в 00:19
поделиться

Я исправил factory girl, чтобы разрешить обратные вызовы after_build и after_create .

Реализация

Factory.class_eval do
  def run (proxy_class, overrides) #:nodoc:
    proxy = proxy_class.new(build_class)
    proxy.callbacks = @callbacks
    overrides = symbolize_keys(overrides)
    overrides.each {|attr, val| proxy.set(attr, val) }
    passed_keys = overrides.keys.collect {|k| Factory.aliases_for(k) }.flatten
    @attributes.each do |attribute|
      unless passed_keys.include?(attribute.name)
        attribute.add_to(proxy)
      end
    end
    proxy.result
  end

  def after_create(&block)
    @callbacks ||= {}
    @callbacks[:after_create] = block
  end

  def after_build(&block)
    @callbacks ||= {}
    @callbacks[:after_build] = block
  end
end

Factory::Proxy.class_eval do
  attr_accessor :callbacks

  def run_callback(name)
    callbacks && callbacks[name] && callbacks[name].call(@instance)
  end
end

Factory::Proxy::Build.class_eval do
  def result
    run_callback(:after_build)
    @instance
  end
end

Factory::Proxy::Create.class_eval do
  def result
    run_callback(:after_build)
    @instance.save!
    run_callback(:after_create)
    @instance
  end
end

Это может быть злой близнец или просто требуемое расширение.

Пример использования

# Models
class User < ActiveRecord::Base
  has_many :items
end

class Items < ActiveRecord::Base
  belongs_to :user
  validates_presence_of :user_id
end

# Factories
Factory.define(:user) do |u|
  u.name "foo"
end

Factory.define(:user_with_items, :parent => :user) do |u|
  u.after_build do |o|
    o.items = [Factory.build(:item, :user => o), Factory.build(:item, :user => o)]
  end
end

Factory.define(:item) do |i|
  i.color "red"
end

Factory.define(:item_with_user, :parent => :user) do |i|
  i.association(:user)
end

# Run
user = Factory(:user_with_items)
user.items(true) # Shows the two saved items

Надеюсь, это поможет кому-то в будущем. Я, вероятно, попытаюсь отправить это ребятам из Thinkbot, но в их трекере ошибок уже есть пара устаревших билетов по этой теме.

11
ответ дан 30 November 2019 в 00:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: