2011-09-15 13 views
2

Rails 3.1およびsqlite3を開発環境、テスト環境に使用します。sqlite3 varcharは "like"と一致しますが、 "="は一致しません。

は、移行中に新しいテーブルを追加しました:ActiveRecordのモデルでは

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 

create_table :api_keys do |t| 
    t.string :api_key 
    t.integer :user_id 
    t.timestamps 
end 

これは、次のスキーマを持つテーブルを作成

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を返します)。同じで:sqlite3ので

ApiKey.where({:api_key => 'something'}).first 

、私は次の操作を行います

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; 

を私はのいずれかから私のクエリに長い16進数文字列を貼り付けることで、既存のレコードを検索しようとした場合既存のレコード:

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を使用して同様の文字列の乱数16進数を生成する他の1つのモデルに影響します。ジェームズ

+0

私はこれは私が3.1をレールにアップグレードするまで言及した第2のモデルクラスに取り組んでいることを追加する必要があります。その時点でテストは失敗し始めました。 –

答えて

8

OK、私はそれを考え出したと思います。問題はこれがRails 3.1ではなく、Ruby 1.8.7からRuby 1.9.2に移行した可能性が高いということです。

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です。 2つ目は、コンソールに入力して作成されたものです。Xは、フィールドが文字列ではなく、ブロブとしてエンコードされていることを示します。この問題を回避するには

、これにあなたのfill_api_keyを変更します。

self.api_key = SecureRandom.hex(30).force_encoding('UTF-8') 

私はちょうどこのことにより、ビット大きな時間を得たので、うまくいけば、それはあなたを助けます。

ここで1.9のStringへの変更に関するいくつかの良い詳細があります:http://blog.grayproductions.net/articles/ruby_19s_string

+0

ありがとう!それはトリックをしたようだ。私はどのように私がログファイルでXを見逃したのか分かりません。 –

0

あなたが進数字の文字列を使用している場合、あなたがここで、x = yの選択を使用したい場合は、ケースの試合を持っていることが重要である

。一部のデータベースとは異なり、SQLiteでは大文字と小文字が区別されます。

+0

ありがとうSteve。それはそうではありません - 私はsqlite3内の文字列をコピーして貼り付けています - それはすべて小文字です、私はすべて小文字を使用しています、私はリテラル文字列を直接コピーしています。 –

+0

上記の例では、選択したINSERTにアルファ16進数はありません。 '1a3bf7'などを使用してSQLiteで直接INSERTを行うとどうなりますか? SELECTはそれを見つけるか?あなたのRailsアプリはありますか?また、この16進数文字列はどれくらいですか? –

+0

16進文字列の長さは60文字(おそらくは過剰)です。私のテストでは、70文字分の小数点以下の文字列を入力してから、文字(小文字、最初は小文字)を約80文字まで追加し始めました。 –

関連する問題