Multiple Records when Importing to Rails via CSV

220 views Asked by At

I'm importing some data into my Rails App via CSV. The import works fine, but when I try and insert contact_name into the accepted attributes, I get an error:

unknown attribute 'contact_name' for Hotel

This field does not belong to the hotel, but if it exists on the spreadsheet I need to create a new Contact and assign it to that hotel, during the import.

 def self.import(file)

  allowed_attributes = [ "id", "status", "rooms", "country_code", "user_id", "hotel_title","hotel_location", "telephone", "email", "contract_date", "print_date", "created_at","updated_at"]
  spreadsheet = open_spreadsheet(file)
  header = spreadsheet.row(1)
  (2..spreadsheet.last_row).each do |i|

    row = Hash[[header, spreadsheet.row(i)].transpose]
    hotel = find_by_id(row["id"]) || new
    hotel.attributes = row.to_hash.select { |k,v| allowed_attributes.include? k }

    # ASSIGNING VARIABLES
    hotel_name = row["hotel_title"]

    hotel.map = Map.create(:hotel_id => row["id"], :status => 0, :title => "Map Publication for #{hotel_name}")
    hotel.app = App.create(:hotel_id => row["id"], :status => 0, :title => "Bespoke App for #{hotel_name}")
    hotel.save!
  end
end

My CSV has 4 columns currently, for simplicity. hotel_title, hotel_location, country_code and contact_name.

2

There are 2 answers

3
Simone Carletti On

If the field doesn't exist in the Hotel model, you can't assign it. It will raise an error here

hotel.attributes = row.to_hash.select { |k,v| allowed_attributes.include? k }

You must remove it from the allowed attributes, and explicitly compose the Contact if the value is present in the row.

if row.to_hash["contact_name"]
  hotel.contact = Contact.new(...)
end

The example above assumes you have a Contact model associated with Hotel.

0
Max Williams On

You can make a setter method contact_name= to do this functionality.

#in Hotel

def contact_name=(name)
  contact = self.contacts.find_by_name(name) || self.contacts.build(:name => name)
end

because you're doing build nothing will be created until the hotel is saved at the end of the update, at which point the contact (if one has been built) will be saved too.