【问题标题】:Activerecord doesn't find record created with CSV infoActiverecord 找不到使用 CSV 信息创建的记录
【发布时间】:2011-07-29 16:45:21
【问题描述】:

当我从 CSV 文件创建记录时,Activerecord 无法使用Record#find_by 找到它们。如果我通过 rails 控制台创建记录,它会按预期工作。这是我通过 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

以下是控制台中的一些示例:

> 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

任何帮助将不胜感激。如果重要的话,我在 Rails 3.1rc5 上。

-

更新为rows.to_hash 输出

根据要求,调试 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"}

控制台中的另一个示例,进一步加深了我的困惑:

> 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

-

已更新 SQL 输出

Record.find_by_email Record.find(14).email生成的SQL:

Record Load (0.3ms)  SELECT "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

-

试用 SQLite 控制台

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

-

添加模型代码、查询结果、CSV输入

可能是人类已知的最令人兴奋的模型:

class Record < ActiveRecord::Base
  attr_accessible :email, :first_name, :last_name, :file
  attr_accessor :file
end

更多查询结果:

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

为了更好的衡量,测试 CSV 文件:

email,first name,last name
Matching@asd.asd,First,Last
Notmatching@asd.asd,Matching,Name
asdasdasdasd@asd.asd,asd,asd

【问题讨论】:

  • 请调试 row.to_hash 在循环中包含的内容。 logger.info row.to_hash.
  • @Casper:我用logger.info row.to_hash 的结果和另一个例子编辑了这个问题。希望对您有所帮助。
  • 嗯。向控制台添加更多调试:ActiveRecord::Base.logger = Logger.new(STDOUT)。它为Record.find_by_email Record.find(14).email 生成什么SQL?
  • 我将 SQL 语句添加到我的问题中。感谢您帮助我解决这个问题。
  • 您使用的是什么数据库?你能去数据库的控制台并在那里运行相同的 SQL 查询吗?..到目前为止一切都很好。不知道为什么没有返回您的 Record 类。您的 Record 模型中是否有任何特殊代码?

标签: ruby-on-rails ruby activerecord csv fastercsv


【解决方案1】:

这是你的问题。从Record 模型中删除所有attr_* 行。默认情况下可以访问所有 ActiveRecord 数据库字段。通过添加 attr 字段,您实际上覆盖了默认的 Rails 访问器,这就是为什么一切都表现得很奇怪。

要学习的一课:当你认为你的模型中“没有什么有趣的东西”时......要非常怀疑:) 祝你好运。删除这些行应该可以解决所有问题。

【讨论】:

  • 啊,要是这么简单就好了。我继续按照您的建议在稳定的 3.0.9 应用程序和空白 3.1.0rc5 应用程序上对其进行了测试。使用 Record.find_by_email 在 3.0.9 应用程序上按预期工作。所以看起来我的问题在于发布候选。再次感谢您帮助我度过难关。转到我要去的错误跟踪器。
【解决方案2】:

原来是编码问题。

电子邮件、名字和姓氏作为 blob 被放入 SQLite,我猜这会导致一两个问题。添加:encoding =&gt; 'u' 作为CSV.foreach 的选项可以解决所有问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多