2009-12-08 3 views
0

j'ai une liste de noms de villes incorrectes aux Philippines:Rails remplacer les attributs dans des tableaux

>> a = City.find_all_by_country_id(4) 

=> [#<City id: 91, name: "Alaminos", country_id: 4, created_at: "2009-11-12 04:06:14", updated_at: "2009-11-12 04:06:14">, #<City id: 92, name: "Angeles", country_id: 4, created_at: "2009-11-12 04:06:14", ... 

Je voulais remplacer tous les noms avec le bon:

=> b = ["Abra", "Agusan del Norte", "Agusan del Sur", ... 

que je voulais utiliser la méthode replace parce que je voulais mettre à jour l'identifiant de ville existant, en l'insérant/tronquant seulement si nécessaire.

Mais je ne peux toujours pas comprendre celui-ci, puisque a est un tableau de tableaux (corrigez-moi si je me trompe) tandis que b est juste un tableau simple, terre-à-terre.

Répondre

0

a devrait être un tableau de modèles City. Par exemple, si vous voulez changer le nom de la ville de l'id de la ville 91 (le premier enregistrement) à "Abra" (le premier élément du tableau), vous feriez simplement a[0].name = b[0]. Je ne sais pas exactement ce que vous essayez de faire, mais j'espère que cela vous permettra de surmonter la partie syntaxique du problème.

+0

Je don Il ne faut pas coder l'identifiant dans le fichier de migration, il serait donc indépendant de la base de données, quel que soit le développement ou la base de données de production. – Khairul

0

Jetez un coup d'œil à Array#zip, et ActiveRecord::Base#update_attribute. Comme le souligne Andy Gaskell, a est un tableau d'objets City. Donc zip peut être appelé sur a, et update_attribute peut être appelé sur n'importe quel élément de a.

La façon simple et bref de faire ce que vous voulez est ceci:

a.zip(b){|array| array[0].update_attribute(:name, array[1])} 

Zip tournera plusieurs tableaux dans un tableau de tableaux. Où chaque index du nouveau tableau est un tableau composé d'éléments dans les tableaux sources du même index. Si vous passez un bloc à zip, Ruby donnera chaque tableau dans c au bloc. C'est un raccourci pratique pour a.zip(b).collect(&block).

Dans le code ci-dessus, array[0] = a[i] et array[1] = b[i], chaque itération fournit une valeur différente de i. update_attributes mettra à jour l'enregistrement dans la base de données en contournant les validations et les rappels.

: Avertissements

  • Si b a plus d'éléments alors vous obtiendrez aucune erreur de méthode.
  • Si a a plus d'éléments que b, le nom des éléments supplémentaires sera "".
  • Encore une fois, Update_attributes contourne les validations et enregistre automatiquement l'enregistrement mis à jour. Si ce n'est pas trop votre aimer vous pouvez remplacer les entrailles du bloc avec:

    array[0].name = array[1]; array[0].save 
    
0

j'ai décidé d'utiliser un fichier de migration à la place, donc c'est le code:

class AddProvinces < ActiveRecord::Migration 
    def self.up 
    philippines = Country.find_by_name('Philippines') 
    old_cities = philippines.cities 
    new_cities = (['Abra', 'Agusan del Norte', 'And all the cities...']) 

    old_cities.each do |c| 
     unless new_cities.blank? 
     City.update(c.id, :name => new_cities.first) 
     new_cities.delete(new_cities.first) 
     else 
     City.delete(c.id) 
     end 
    end 

    unless new_cities.blank? 
     new_cities.each do |c| 
     City.create(:name => c, :country_id => 'philippines.id') 
     end 
    end 
    end 

    def self.down 
    end 
end 
Questions connexes