【发布时间】:2021-08-06 07:46:42
【问题描述】:
我正在使用一个旧的 MySQL 数据库,我尝试使用 Rails 与之交互,创建记录时出现错误:
2.7.2 :005 > HashRef.create!(hash: '00080e597c26a05197aaa4462e53cdf9847b56a4d5d47e550fdc01554434df8gg2fffsss')
TRANSACTION (0.2ms) BEGIN
HashRef Create (0.3ms) INSERT INTO `hash_ref` (`hash`) VALUES ('00080e597c26a05197aaa4462e53cdf9847b56a4d5d47e550fdc01554434df8gg2fffsss')
TRANSACTION (4.7ms) COMMIT
Traceback (most recent call last):
2: from (irb):4
1: from (irb):5:in `rescue in irb_binding'
TypeError (no implicit conversion of String into Integer)
这似乎是因为 DB 表有一个名为 hash(主键)的字符串列,它与某些 Rails 内容冲突。
CREATE TABLE `hash_ref` (
`hash` varchar(512) NOT NULL,
`cipher` varchar(512) DEFAULT NULL,
`clear` varchar(512) DEFAULT NULL,
`record_insert_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`hash`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
我可以给属性起别名,但这会在写入时引发同样的错误。
alias_attribute :my_hash, :hash
很遗憾,此时重命名列不是一个选项。
我原以为有某种方法可以代理列名,所以我可以在代码中将其称为my_hash,但当它查询数据库时,它使用hash。
我在另一个答案中看到了这个猴子补丁,这似乎有效,但我想知道这样做是否安全:
class << self
def instance_method_already_implemented?(method_name)
return true if method_name == 'hash'
super
end
end
也有推荐的gem,但是很多年没更新了:
https://github.com/bjones/safe_attributes
我唯一能想到的就是使用原始 SQL 来写入这个 DB,但是在编写 RSpec 测试时无法使用模型或工厂非常尴尬。
感谢您的帮助
【问题讨论】:
-
老实说,我不知道什么最有效,这是你所处的一个非常不幸的位置。我需要尝试不同的想法来尝试什么有效,但我猜你我现在比我现在处于更好的位置。
-
但是,我在查看时发现的另一种可能性是here:也许您可以使用
default_scope :select=> 'hash as hash_value'之类的东西来重命名属性? -
但正如下面回答的那样,重命名列可能真的只是最简单的解决方案吗?...我知道你说“这不是一个选择”,但也许你对该声明的理由会被否决不同解决方法的复杂性/危险性。
标签: ruby-on-rails ruby legacy-code