Rails无法移除" \ r \ n"从记录

时间:2014-05-04 23:39:43

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

我导入了一些数据com的CSV文件,最后得到了一些包含字符串" \ r \ n"在一列中。当再次导出为CSV时,这些行会在插入新行时将这些行搞砸......

我尝试使用Rake任务删除,但似乎ActiveRecord没有发出UPDATE查询,我无法弄清楚我做错了什么......

这就是我正在做的事情:

Contact.all.each {|c| 
    next if c.address.nil? || !c.address.include?("\r\n"); 
    c.address.gsub!("\r\n", " - "); 
    c.save; 
}

这是rails c -s会话的输出:

(1.7ms)  SAVEPOINT active_record_1
(0.1ms)  RELEASE SAVEPOINT active_record_1
(0.0ms)  SAVEPOINT active_record_1
(0.0ms)  RELEASE SAVEPOINT active_record_1
(0.1ms)  SAVEPOINT active_record_1
(0.1ms)  RELEASE SAVEPOINT active_record_1
(0.0ms)  SAVEPOINT active_record_1
(0.0ms)  RELEASE SAVEPOINT active_record_1

没有发布UPDATE ......

关于它为什么不起作用的任何想法?

2 个答案:

答案 0 :(得分:2)

您的问题是gsub!就地修改了字符串:

  

gsub!(模式,替换)→str或nil
   gsub!(模式){|匹配|阻止}→str或nil
   gsub!(模式)→an_enumerator

     

如果没有执行替换,则执行String#gsub的替换,返回 str nil。 [...]

gsub非常乐意将String作为其第一个参数:

  

gsub(模式,替换)→new_str    gsub(模式,哈希)→new_str
   gsub(模式){|匹配| block}→new_str
   gsub(模式)→枚举器

     

[...] 模式通常为Regexp;如果作为String给出,它包含的任何正则表达式元字符将按字面解释[...]

因此s.gsub!("\r\n", ' - ')s.gsub!(/\r\n/, ' - ')会产生完全相同的效果。

那么当您使用gsub!时会发生什么?如果你这样做:

c.address.gsub!("\r\n", " - ")

您以ActiveRecord无法识别的方式更改c.address。例如,在Rails控制台中尝试这个:

> c = Address.find(some_valid_id)
> c.address.gsub!('e', 'x') # Assuming that the address has an 'e' in it of course...
> c.changed?
 => false
> c.address_changed?
 => false

所以你已经改变了地址字符串,但ActiveRecord不知道因为c.address仍然是同一个String对象。由于ActiveRecord认为没有任何变化,c.save不会做任何事情。

如果您切换到gsub版本:

c.address = c.address.gsub("\r\n", ' - ')

然后您将使用全新的字符串替换c.address,而c.address_changed?c.changed?都将为真。现在,ActiveRecord会识别您已更改cc.save(或c.save!)会向您的数据库发送更新。

请注意,gsub!有时返回nil在此处完全无关紧要,代码中的任何内容都不会查看gsub!返回的内容,因此返回的内容并不重要。


我可能会使用SQL在数据库内部做这类事情,但是你如何做的具体细节取决于底层数据库。每当我想说Model.all时,我都会畏缩,因为我曾经常常处理大型数据库,使用all只是一种方便的方式来摧毁你的记忆。

答案 1 :(得分:1)

使用String.encode(universal_newline: true)代替gsub。 它将CRLF和CR转换为LF