2016-10-26 1 views
3

Tenir compte de la configuration du modèle suivantComment puis-je transmettre des attributs à une association via un trait dans factorygirl?

class Template < ActiveRecord::Base 
    belongs_to :detail, polymorphic: true, dependent: :destroy 
    accepts_nested_attributes_for :detail 
end 

class EbayTitleTemplate < ActiveRecord::Base 
    has_one :template, as: :detail 
end 

Et voici une usine de travail

FactoryGirl.define do 
    factory :template do 
    merchant 
    channel 

    trait :ebay_title do 
    association :detail, factory: :template_ebay_title 
    end 

    factory :ebay_title_template, traits: [:ebay_title] 
    end 

    factory :template_ebay_title, class: EbayTitleTemplate do 
    name  "eBay Title Template" 
    title  "Super Cool Hat" 
    sub_title "Keeps the sun away" 
    description "The best hat available!" 
    end 
end 

Les œuvres suivantes pour moi

create(:ebay_title_template) # creates both records, creating a new Merchant and Channel for me 
create(:ebay_title_template, merchant: Merchant.first, channel: Channel.first) # creates both records with explicit channel and merchant 

Maintenant, ce que je voudrais faire aussi est passe dans les attributs personnalisés pour remplacer les valeurs par défaut. Quelque chose comme ceci:

create(:ebay_title_template, title: "Overwrite the title", sub_title: "Overwrite the subtitle") 

Ce qui finit par se produire est que je reçois l'erreur ArgumentError: Trait not registered: title

D'une certaine façon factorygirl pense que je passe dans un trait ou l'usine de modèle ne reconnaît pas title comme attribut.

J'ai essayé d'utiliser transitoires pour permettre args personnalisés de passer à travers le modèle et en utilisant un rappel en usine :template_ebay_title pour cartographier l'attribut à la colonne de modèle comme ceci:

transient do 
    custom_args nil 
end 

after(:create) do |record, evaluator| 
    evaluator.custom_args.each do |key, value| 
    record.key = value 
    end 
end 

Et puis je crée comme ceci:

create(:ebay_title_template, custom_args: {title: "Overwrite", sub_title: "Overwrite"}) 

il en résulte l'erreur NoMethodError: undefined method custom_args' pour # `

donc, soit il y a un moyen de d o ceci et je le fais mal, ou j'ai besoin d'une approche complètement nouvelle. Gardez à l'esprit qu'il y aura des douzaines d'associations qui devront être définies comme des traits (ou quelque chose d'autre), donc je ne peux pas assigner des transitoires spécifiques à traverser.

Comment puis-je atteindre mon objectif de créer une fabrique qui crée le parent et l'association polymorphique, ce qui me permet de transmettre des attributs arbitraires pour l'association polymorphique et de renvoyer l'objet parent?

+0

Quelle version de FactoryGirl utilisez-vous? Apparemment avant 5.0, vous devez utiliser 'ignore' à la place de' transitoire' - source: [méthodes non définies pour les variables transitoires factorygirl] (http://stackoverflow.com/questions/25510268/undefined-methods-for-factorygirl-transient -variables) – David

+0

J'utilise factory_girl_rails 4.5. J'ai essayé «ignore» à la place de «transitoire» et j'ai eu la même erreur. – cheeseandpepper

Répondre

1

Si vous êtes désireux de transmettre les valeurs au sein d'une seule valeur de hachage, vous devez les passer comme ceci:

create(:ebay_title_template, custom_args: {title: "Overwrite the title", sub_title: "Overwrite the subtitle"}) 

Sinon, vous pouvez créer de nouvelles valeurs transitoires, et les transmettre la façon dont vous passez les maintenant:

transient do  # use ignore with FactoryGirl/FactoryBot < v4.7 
    title nil 
    sub_title nil 
end 

Lors de l'ajout d'autres attributs comme ci-dessus, vous pouvez alors itérer sur la overrides variable d'instance de l'évaluateur:

evaluator.instance_variable_get(:@overrides).each do |key, value| 
    puts key, value 
end 

Espérons que ça aide!