使用Rails3.1和sqlite3进行开发和测试环境。
在迁移中添加了新表:
create_table :api_keys do |t|
t.string :api_key
t.integer :user_id
t.timestamps
end这将生成一个具有以下模式的表:
create_table "api_keys", :force => true do |t|
t.string "api_key"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
end在ActiveRecord模型中:
before_create :fill_api_key
private
def fill_api_key
self.api_key = SecureRandom.hex(30)
endActiveRecord的动态查找器方法find_by_api_key(api_key)不起作用(返回nil)。同上:
ApiKey.where({:api_key => 'something'}).first在sqlite3中,我执行以下操作:
insert into api_keys (id, api_key) values (-1, '12345');如果我现在运行select:
select api_keys.* from api_keys where api_keys.api_key = '12345';将会找到该记录。
如果我运行未过滤的select命令,则会显示从我的应用程序创建的预先存在的数据:
select api_keys.* from api_keys;如果我试图通过在查询中粘贴一个来自这些预先存在的记录之一的长十六进制字符串来查找预先存在的记录:
select api_keys.* from api_keys where api_keys.api_key = 'long hex string';则不返回任何结果。如果我尝试这样做:
select api_keys.* from api_keys where api_keys.api_key like 'long hex string';然后我就会得到一个匹配。
我已经在api_keys.api_key上创建了一个索引,但没有任何效果。
这个问题影响了我的应用程序中的另一个模型,该模型使用Digest::SHA1::hexdigest生成类似的随机十六进制数字字符串。
詹姆斯
发布于 2011-09-19 08:28:10
好了,我想我已经弄明白了。问题不在于这是Rails 3.1,而是你可能已经从Ruby 1.8.7迁移到了Ruby 1.9.2。
在Ruby1.9中,所有的字符串现在都是编码的。默认情况下,所有字符串都应为UTF-8,但是,SecureRandom.hex(30)将返回ASCII-8BIT编码。
您可以使用以下命令在sqlite3中确认这一点:.dump api_keys,您可能会看到api_key字段如下所示:
INSERT INTO "api_keys" VALUES(1,X'376433356530[...]',1);
INSERT INTO "api_keys" VALUES(1,'1234567890[...]',1);第一个是由SecureRandom生成的api_key。第二个是通过在控制台中键入来创建的。X表示字段编码为blob,而不是字符串。
要解决此问题,请将您的fill_api_key更改为:
self.api_key = SecureRandom.hex(30).force_encoding('UTF-8')我刚刚通过这个得到了bit big time,所以希望它能帮助你。
这里有一些关于1.9中对字符串的更改的好细节:http://blog.grayproductions.net/articles/ruby_19s_string
发布于 2011-09-16 06:09:00
如果您使用十六进制数字字符串,如果您想要使用where x=y select,大小写匹配是很重要的。与某些数据库不同,SQLite区分大小写。
https://stackoverflow.com/questions/7437944
复制相似问题