Rails无法从记录中删除“\ r \ n”

问题描述 投票:3回答:2

我已导入一些数据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发布......

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

ruby-on-rails ruby csv activerecord rails-activerecord
2个回答
2
投票

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

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

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

gsub很高兴有一个String作为它的第一个参数:

gsub(模式,替换)→new_str gsub(模式,哈希)→new_str gsub(pattern){| match | 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", ' - ')

那么你将用一个全新的String替换c.address,而c.address_changed?c.changed?都将成为现实。现在,ActiveRecord将识别您已更改c并且c.save(或c.save!)将向您的数据库发送UPDATE。

请注意,gsub!有时返回nil在这里完全无关紧要,你的代码中没有任何内容可以查看gsub!返回的内容,因此返回它并不重要。


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


1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.