Reputation: 6659
Rails 5.1
My migration file:
class CreateFwExports < ActiveRecord::Migration[5.1]
def change
create_table :fw_exports, id: :string do |t|
t.string :screen_name, index: true, limit: 16
t.string :full_name, limit: 21
t.string :location
t.timestamps
end
end
end
In my helper file, I have the following method:
def process_spreadsheet(number_of_rows, spreadsheet)
for i in 1..number_of_rows do
fw_export_record = FwExport.new(
:screen_name => spreadsheet[i][0].to_s,
:full_name => spreadsheet[i][1].to_s,
:location => spreadsheet[i][2].to_s,
)
fw_export_record.save
end
end
What this method does, is receive a spreadsheet CSV object, and iterates through the data, trying to save each row to the fw_exports table.
The first data row is:
xxxxxxxx,xxxxxxxxxx,"Nottingham, England"
I am getting the following error message:
ActiveRecord::AssociationTypeMismatch (Location(#38400060) expected, got "Nottingham, England" which is an instance of String(#10657520)):
app/helpers/fw_exports_helper.rb:21:in `block in process_spreadsheet'
app/helpers/fw_exports_helper.rb:20:in `process_spreadsheet'
app/controllers/fw_exports_controller.rb:82:in `process_parsed_spreadsheet'
When I looked at the actual MySQL table, here's what I got:
id Primary varchar(255) utf8mb4_unicode_ci No None
screen_name varchar(16) utf8mb4_unicode_ci Yes NULL
full_name varchar(21) utf8mb4_unicode_ci Yes NULL
location varchar(255) utf8mb4_unicode_ci Yes NULL
From the controller:
def fw_export_params
params.require(:fw_export).permit(:screen_name, :full_name, :location)
end
id is generated through a method defined in the concerns section
Any idea why I'm getting the error message?
In my fw_exports.rb model, I had the following:
has_one :location
I have a locations table (and model), with the following fields:
t.string :fw_exports_id, index: true
t.string :city
t.string :state
t.string :country
When I commented out, the line in the fw_exports.rb model:
# has_one :location
I stopped getting the above mentioned error, and instead, I am now getting the following error:
NoMethodError (undefined method `each' for "0":String):
app/helpers/fw_exports_helper.rb:21:in `block in process_spreadsheet'
app/helpers/fw_exports_helper.rb:20:in `process_spreadsheet'
app/controllers/fw_exports_controller.rb:82:in `process_parsed_spreadsheet'
Same spot in code, different message.
Upvotes: 3
Views: 2483
Reputation: 3960
As you have:
class FwExport < ApplicationRecord
has_one :location
and assuming that:
class Location < ApplicationRecord
belongs_to :fw_export
so you cannot define :location
as a string column in CreateFwExports
migration.
First you need to write another migration to remove the column from :fw_exports
table:
class RemoveColumnFromFwExports < ActiveRecord::Migration[5.1]
def change
remove_column :fw_exports, :location, :string
end
end
Now rewrite the helper method that would parse the location string from csv into a Location
instance and assign it into the FwExport
instance:
def process_spreadsheet(number_of_rows, spreadsheet)
1.upto(number_of_rows) do |i|
fw_export_record = FwExport.new(
screen_name: spreadsheet[i][0].to_s,
full_name: spreadsheet[i][1].to_s,
)
fw_export_record.save
# now create the location and associate it to fw_export_record
location = find_or_create_location(spreadsheet[i][2].to_s)
location.fw_exports_id = fw_export_record.id
location.save
end
end
private
def find_or_create_location(s)
city, country = s.split(',').map(&:strip)
Location.find_or_create_by!(city: city, country: country)
end
Upvotes: 0
Reputation: 1464
Add |i|
after the do
for i in 1..number_of_rows do |i|
Edit after response in comment:
You don't show the model but probably you have a relationship called location
that is conflicting with the field.
Upvotes: 2