使用Rails 3.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)
end
ActiveRecord的动态查找程序方法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 api_keys.* from api_keys where api_keys.api_key = '12345';
将找到记录。
如果我运行未经过滤的选择,则会显示从我的应用程序创建的预先存在的数据:
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生成类似的随机十六进制数字字符串。
詹姆斯
答案 0 :(得分:8)
在Ruby 1.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')
我刚才有点 大时间 ,所以希望它可以帮助你。
这里有关于1.9中字符串更改的一些很好的细节:http://blog.grayproductions.net/articles/ruby_19s_string
答案 1 :(得分:0)
如果您使用的是十六进制数字字符串,如果您想使用其中x = y select,则必须具有大小写匹配。与某些数据库不同,SQLite区分大小写。