2017-05-02 1 views
1

Essayer de comprendre comment faire cela via la console Rails.Rails 4 Associations ActiveRecord: mise à jour de collectionproxy via la console Rails

Abonnement - a de nombreuses catégories Catégorie - appartient à la souscription

Il y avait 9 catégories, mais je dois ajouter un dixième.

S'ils étaient abonnés à la catégorie # 9, je veux qu'ils soient déjà abonnés à la catégorie # 10 en l'ajoutant. Donc, ça va être quelque chose comme:

subs = Subscription.all 
subs.each do |sub| 
    if sub.categories.where(name: "Category Number One").exists? 
    puts "it does indeed exist." #update this line to add "Category Number 2" to sub.categories 
    else 
    puts "it does NOT exist." 
    end 
end 

Je suis un peu confus sur ce qu'il faut faire avec le bloc if. On dirait qu'il existe une méthode pour ce que je veux faire (notez que category_ids est un Array):

http://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-3C-3C

Qu'est-ce que je passe exactement bien?

Si je tente avec l'ID de catégorie réelle en utilisant sub.categorizations << 10, je reçois:

ActiveRecord::AssociationTypeMismatch: Categorization(#70215789049700) expected, got Fixnum(#70215753183840)

Toute idée sur la façon d'attaquer ce problème, la bonne façon serait grandement apprécié.

Répondre

1

créer via

sub.categories.create (nom: "Catégorie Numéro 2")

+0

Je vous suggère de le faire avec un 'ActiveRecord :: Transaction', car il veut que certains d'entre eux de souscrire à cette catégorie lors de sa création – Minato

+0

Ah, désolé, je mispoke peut-être. La catégorie 10 existe DÉJÀ avant la mise à jour de ces abonnements). J'ai essayé ceci: 'sub.categorizations << Categorization.where (category_id: 10)' mais il a ajouté la catégorie # 10 deux fois. Pourquoi cela serait-il? – DnfD

+1

b/c votre schéma est faux. vous vouliez avoir quelque chose comme l'abonnement has_many: subscription_categories, qui serait juste une table jointe à Categories. – Rob

0

Créer une nouvelle Categorization avec l'ID de l'abonné était le chemin à parcourir. Aussi, ne visitons pas tous les abonnements, seulement ceux que nous devons changer, et visitons-les par lots pour minimiser l'utilisation de la mémoire.

cat1 = Category.where(:name: "Category One").first! 
Subscription.joins(:categorizations).where(:categorizations=>{:category_id=>cat1.id).find_each do |sub| 
    sub.categorizations.create(category_id: 10) 
end 
+1

Bien sûr, un problème avec la visite de chaque sous-marin comme ceci est que vous aurez un problème de base de données N + 1. Mieux serait 1) aller chercher seulement les enregistrements dont vous avez besoin 2) les traiter par lot – Rob