我导入了一些数据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 ......
关于它为什么不起作用的任何想法?
答案 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会识别您已更改c
,c.save
(或c.save!
)会向您的数据库发送更新。
请注意,gsub!
有时返回nil
在此处完全无关紧要,代码中的任何内容都不会查看gsub!
返回的内容,因此返回的内容并不重要。
我可能会使用SQL在数据库内部做这类事情,但是你如何做的具体细节取决于底层数据库。每当我想说Model.all
时,我都会畏缩,因为我曾经常常处理大型数据库,使用all
只是一种方便的方式来摧毁你的记忆。
答案 1 :(得分:1)
使用String.encode(universal_newline: true)
代替gsub。
它将CRLF和CR转换为LF