Rails CSV импорт, добавление в связанную таблицу - PullRequest
4 голосов
/ 13 мая 2010

В моем приложении есть система импорта csv (используется только локально), которая построчно анализирует файл CSV и добавляет данные в таблицу базы данных. Это основано на учебнике здесь .

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

Это все в контроллере курсов и работает нормально. Существует связь, которая обучает HABTM лет и лет HABTM курсов. В файле csv (фактически в строках [5] - в строке [8]) указываются значения year_id. Есть ли способ, которым я могу добавить это в методе выше. Я не совсем понимаю, как перебрать 4 элемента и добавить их в таблицу courses_years.

Спасибо Jack

Ответы [ 2 ]

2 голосов
/ 13 мая 2010

Вы можете сделать это, добавив простой цикл после того, как ваши «нормальные» данные добавлены в модель, и используя метод << для добавления в ассоциацию лет. </p>

...
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
...

Вы можете добавить больше проверок в цикл, если хотите убедиться, что значения действительны, и / или изменить поиск, чтобы найти свой год по-другому. Другой способ, когда связанные данные «отстают от конца», как это, состоит в том, чтобы продолжать добавлять, пока не останется ничего добавить, а также добавлять сами годы, если они еще не существуют:

...
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
...

Есть много разных способов сделать это, и правильный путь действительно зависит от ваших реальных данных, но это основной метод.

1 голос
/ 13 мая 2010

Вы пытались поставить один из них, прежде чем сохранить курс:

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

OR

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

Поместите его перед сохранением курса. Это заполнит объединенную таблицу курсы_год.

EDIT

Похоже, ошибка, которую вы получаете, потому что мы пытаемся поместить идентификаторы вместо объектов, мы должны сделать это вместо:

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

После того, как мы получили объекты года, мы помещаем их в ассоциацию. После этого вы можете сохранить объект курса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...