2010-05-13 5 views
3

J'ai un système d'importation csv sur mon application (utilisé localement seulement) qui analyse le fichier csv ligne par ligne et ajoute les données à la table de la base de données. Ceci est basé sur un tutoriel here.Rails Importation CSV, ajout à une table associée

require 'csv' 

def csv_import 
    @parsed_file=CSV::Reader.parse(params[:dump][:file]) 
    n = 0 
    @parsed_file.each_with_index do |row, i| 
    next if i == 0 #ignore the first row 
    course = Course.new 
    course.title = row[0] 
    course.unit_code = row[1] 
    course.course_type = row[2] 
    course.value = row[3] 
    course.pass_mark = row[4] 
    if course.save 
     n = n+1 
     GC.start if n%50==0 
    end 
    flash.now[:message] = "CSV Import Successful, #{n} new courses added to the database." 
    end 
    redirect_to(courses_url) 
end 

Ceci est tout dans le contrôleur de cours et fonctionne très bien. Il y a une relation qui cours HABTM ans et années cours HABTM. Dans le fichier csv (effectivement dans la rangée [5] à la rangée [8]) sont les year_id s. Y at-il un moyen que je peux ajouter ceci dans la méthode ci-dessus. Je suis confus quant à la façon de faire une boucle sur les 4 éléments et de les ajouter à la table courses_years.

Merci Jack

Répondre

2

Vous pouvez le faire en ajoutant une simple boucle après l'ajout de vos données "normales" au modèle, et en utilisant la méthode < < pour ajouter à l'association years.

... 
course.value = row[3] 
course.pass_mark = row[4] 
5.upto(8).each do |i| 
    one_year = Year.find(row[i]) 
    course.years << one_year if one_year 
end 
if course.save 
    n = n+1 
... 

Vous pouvez ajouter plus de contrôles dans la boucle si vous voulez vous assurer que les valeurs sont valides et/ou modifier la découverte pour localiser votre année d'une autre manière. Une autre façon lorsque les données connexes est « traîne l'extrémité » comme celui-ci est de continuer à ajouter jusqu'à ce qu'il n'y a plus rien à ajouter, et aussi d'ajouter les années eux-mêmes si elles ne sont pas encore réunies:

... 
course.value = row[3] 
course.pass_mark = row[4] 
row[5..-1].each do |year_id| 
    one_year = Year.find_or_create_by_id(year_id) 
    course.years << one_year 
end 
if course.save 
    n = n+1 
... 

Il Il y a beaucoup de façons différentes de le faire, et la façon de procéder dépend vraiment de vos données réelles, mais c'est la méthode de base.

+0

Excellent. Merci beaucoup. Avez-vous une idée d'où je peux en savoir plus sur la méthode < Jack

+1

apidock.com est un excellent site pour la recherche de documentation relative aux rails. Vous cherchez des méthodes d'association ActiveRecord je pense: http://apidock.com/rails/ActiveRecord/Associations/ClassMethods – jamuraa

+0

Bingo. Super site. Une dernière chose.Lorsque j'utilise votre deuxième exemple, le serveur semble être coincé dans une boucle. Est-ce que je manque quelque chose? – Jack

1

Avez-vous essayé de mettre l'un de ceux-ci avant d'enregistrer le cours:

course.years.push(row[5]) 
course.years.push(row[6]) 
course.years.push(row[7]) 
course.years.push(row[8]) 

OU

course.years = [ row[5], row[6], row[7], row[8] ] 

Placez-le avant d'enregistrer le cours. Il remplira la table conjointe courses_years.

EDIT

L'erreur que vous obtenez semble être parce que nous essayons de mettre ids au lieu des objets, nous devons le faire à la place:

..... 
    year_array = Year.find(row[5], row[6], row[7], row[8]) 
    course.years << year_array 
    ..... 

Après avoir obtenu les objets de l'année, alors nous l'avons mis dans l'association. Vous pouvez enregistrer l'objet du cours après cela.

+0

Merci pour la réponse. Je continue d'obtenir l'erreur suivante: Année (# 2183546760) attendue, a obtenu CSV :: Cell (# 2156593920) Des suggestions? – Jack

+1

Vérifiez ma réponse éditée, je suppose que les données du modèle de l'année est disponible, sinon, nous le ferons différemment. –

+0

Excellent, bravo. Existe-t-il un moyen simple de placer une boucle autour de la création du tableau, de sorte que si une cellule était vide, elle l'ignorait? jamuraa l'a essayé dans son code, mais cela ne semble pas fonctionner. Des idées? – Jack

Questions connexes