When I create Records from a CSV file, Activerecord can't find them with Record#find_by
. If I create a Record through the rails console, it works as expected. Here's my code for creating through CSV:
def create
file = params[:record][:file].tempfile
CSV.foreach file, :headers => true, :header_converters => :symbol do |row|
Record.create row.to_hash
end
redirect_to records_url
end
Here are some examples from the console:
> Record.find_by_email "matching@asd.asd"
=> nil # Should return record created through the CSV file
> Record.create :email => "matching@asd.asd"
> Record.find_by_email "matching@asd.asd"
=> <Record id: 4, email: "matching@asd.asd">
> Record.find_all_by_email "matching@asd.asd"
=> [<Record id: 4, email: "matching@asd.asd">] # Should return both
Any help would be appreciated. I'm on Rails 3.1rc5 if it matters.
-
Updated with rows.to_hash
output
As requested, the output from debugging rows.to_hash:
{:email=>"Matching@asd.asd", :first_name=>"First", :last_name=>"Last"}
{:email=>"Notmatching@asd.asd", :first_name=>"Matching", :last_name=>"Name"}
{:email=>"asdasdasdasd@asd.asd", :first_name=>"asd", :last_name=>"asd"}
Another example from the console, which furthers my confusion:
> Record.find 14 # Record created by CSV
=> <Record id: 14, first_name: "First", last_name: "Last", email: "Matching@asd.asd", created_at: "2011-07-29 18:03:25", updated_at: "2011-07-29 18:03:25">
> Record.find(14).email
=> "Matching@asd.asd"
> Record.find_by_email Record.find(14).email
=> nil
-
Updated with SQL output
SQL generated by Record.find_by_email Record.find(14).email
:
Record Load (0.3ms) SEL开发者_JS百科ECT "records".* FROM "records" WHERE "records"."id" = ? LIMIT 1 [["id", 14]]
Record Load (0.3ms) SELECT "records".* FROM "records" WHERE "records"."email" = 'Matching@asd.asd' LIMIT 1
-
Trying out the SQLite console
sqlite> SELECT "records".* FROM "records" WHERE "records"."email" = 'Matching@asd.asd' LIMIT 1;
# This one should have returned the CSV record, but it returns nothing
sqlite> SELECT "records".* FROM "records" WHERE "records"."email" = 'nomatch@asd.asd' LIMIT 1;
5|2|match|this|nomatch@asd.asd|2011-07-29 17:13:13.821972|2011-07-29 17:13:13.821972
-
Adding model code, query results, CSV input
Possibly the most exciting model known to man:
class Record < ActiveRecord::Base
attr_accessible :email, :first_name, :last_name, :file
attr_accessor :file
end
More results from the query:
sqlite> select * from records;
5|2|match|this|nomatch@asd.asd|2011-07-29 17:13:13.821972|2011-07-29 17:13:13.821972
9|3|first|last||2011-07-29 17:56:50.471766|2011-07-29 17:56:50.471766
10|6|first|last||2011-07-29 17:56:54.917432|2011-07-29 17:56:54.917432
17||First|Last|Matching@asd.asd|2011-07-29 19:43:23.843188|2011-07-29 19:43:23.843188
18||Matching|Name|Notmatching@asd.asd|2011-07-29 19:43:23.849001|2011-07-29 19:43:23.849001
19||asd|asd|asdasdasdasd@asd.asd|2011-07-29 19:43:23.852037|2011-07-29 19:43:23.852037
For good measure, the test CSV file:
email,first name,last name
Matching@asd.asd,First,Last
Notmatching@asd.asd,Matching,Name
asdasdasdasd@asd.asd,asd,asd
Here is your problem. Remove all attr_*
lines from your Record
model. All ActiveRecord
database fields are accessible by default. By adding attr
fields you are effectively overwriting the default Rails accessors and that's why everything is acting weird.
Lesson to learn: when you think you have "nothing interesting" in your model...be very suspicious :) Good luck. Removing those lines should fix everything.
It turned out to be an encoding problem.
The email, first name and last name were thrown into SQLite as blobs, which I guess causes a problem or two. Adding :encoding => 'u'
as an option for CSV.foreach
fixed everything up.
精彩评论