【问题标题】:UnknownAttributeError csv未知属性错误 csv
【发布时间】:2016-05-13 23:36:47
【问题描述】:

尝试将 csv 记录上传到城市模型数据库,出现错误

ActiveRecord::UnknownAttributeError in PagesController#import

unknown attribute 'country ' for City.  (City.create! row.to_hash)

csv:

name     country    general_info1    general_info2 (etc)
Toronto  Canada     This is a test   (nil)

上传视图

<%= form_tag upload_path, multipart: true do %>
  <%= file_field_tag :file %>
  <%= submit_tag "import" %>
<% end %>

路线:

post '/upload' => 'pages#import'

页面控制器

def import
    City.import(params[:file])
end

城市模型

def self.import(file)
    logger.info "__________________"
    logger.info file.inspect
    logger.info file.path
    logger.info "__________________"

    CSV.foreach(file.path, headers: true) do |row|
      City.create! row.to_hash
      #puts '&&&&&&&&&&&&&&&&&&&&&&&' + row[1]
      logger.info row.inspect
    end

架构

ActiveRecord::Schema.define(version: 20160513090837) do

  create_table "cities", force: :cascade do |t|
    t.string   "name"
    t.string   "country"
    t.string   "general_info1"
    t.string   "general_info2"
    t.integer  "happiness_rating"
    t.integer  "family_safety_rating"
    t.string   "family_safety_info"
    t.integer  "bike_hobby_rating"
    t.string   "bike_hobby_info"
    t.integer  "accountant_rating"
    t.integer  "accountant_shortage_rating"
    t.string   "accountant_shortage"
    t.integer  "accountant_avg_salary"
    t.integer  "graphic_designer_rating"
    t.string   "graphic_designer_shortage"
    t.integer  "graphic_designer_avg_salary"
    t.integer  "journalist_rating"
    t.string   "journalist_shortage"
    t.integer  "journalist_avg_salary"
    t.datetime "created_at",                  null: false
    t.datetime "updated_at",                  null: false
  end

end

提前多谢

答案:

CSV.foreach(file.path, {headers: true, header_converters: :symbol}) do |row|
        City.create!(row.to_hash)
      end

【问题讨论】:

  • ...有人能解释一下为什么标题需要是一个符号吗?谢谢

标签: ruby-on-rails csv


【解决方案1】:

首先,如果City 模型的create! 方法期望出现在cities 表中的field 不存在,则会出现ActiveRecord::UnknownAttributeError。确保它在那里。

谁能解释一下为什么标题需要是一个符号?

当您在 ruby​​ 中解析 CSV 时,您通常会以 Hashes 的集合形式获取数据。在下面的示例中,您可能已经注意到 keys 到所有 Hashes 都在重复,它们是 String 数据。在Ruby 中,每个String 实例占用单独的内存空间。

csv.to_a.map {|row| row.to_hash }
# => [{"Year"=>"1997", "Make"=>"Ford", "Model"=>"E350", "Description"=>"ac, abs, moon", "Price"=>"3000.00"}, {"Year"=>"1999", "Make"=>"Chevy", "Model"=>"Venture \"Extended Edition\"", "Description"=>"", "Price"=>"4900.00"}, {"Year"=>"1999", "Make"=>"Chevy", "Model"=>"Venture \"Extended Edition, Very Large\"", "Description"=>nil, "Price"=>"5000.00"}, {"Year"=>"1996", "Make"=>"Jeep", "Model"=>"Grand Cherokee", "Description"=>"MUST SELL!\nair, moon roof, loaded", "Price"=>"4799.00"}]

说字符串computer 占用8 bytes。如果我定义这个字符串1000,000 次,它将占用我的RAM 的8MB

现在如果您使用header_converters: :symbol,这将调用to_sym 方法,该方法现在将keys 定义为symbols。

csv = CSV.new(body, :headers => true, :header_converters => :symbol)
csv.to_a.map {|row| row.to_hash }
# => [{:year=>"1997", :make=>"Ford", :model=>"E350", :description=>"ac, abs, moon", :price=>"3000.00"}, {:year=>"1999", :make=>"Chevy", :model=>"Venture \"Extended Edition\"", :description=>"", :price=>"4900.00"}, {:year=>"1999", :make=>"Chevy", :model=>"Venture \"Extended Edition, Very Large\"", :description=>nil, :price=>"5000.00"}, {:year=>"1996", :make=>"Jeep", :model=>"Grand Cherokee", :description=>"MUST SELL!\nair, moon roof, loaded", :price=>"4799.00"}]

符号有什么特别之处?

Symbol 内存效率高,检索速度非常快。如果定义符号:computer1000,000 次,它只会占用8Bytes 的内存。

这个解释如何解决我的问题?

您的 CSV 文件可能有数千行数据要转换为 Hash。所以为了让这个过程更快和内存效率更高,你使用header_converters: :symbol

更多信息请参见http://ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html#HeaderConverters

【讨论】:

  • 好的,谢谢!但事实仍然是,在我添加 header_converters: :symbol 选项之前,City 实例为 csv/数据库转换带回了 nil,和/或给了我一个 UnknownAtrributeError,我忘记了。当我添加符号选项时,它神奇地起作用了。
  • previous,我尝试在模型中添加一个def init和一个attr_accessor,这也导致了同样的错误。但是您可以从架构中看到,我在那里有“国家”,并且我相应地排列了 csv...row[1] 是“加拿大”。符号选项必须以某种方式将 csv 与适当的模型对齐,无论是什么、属性,但我不知道如何以及为什么。
  • 我也试过 #City.create!({ #name => row[0], #country => row[1], #general_info1 => row[2], # }) 当我添加了定义 attr_accessors 无济于事
猜你喜欢
  • 2018-01-16
  • 1970-01-01
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
  • 2015-11-05
  • 2021-12-06
  • 1970-01-01
相关资源
最近更新 更多