2016-04-19 7 views
1

私はRails4のストア機能を使用しています。私は新たに格納された属性、つまり4人のアクセサを持つ "友人"を追加しました。Rails 4:どこでストア(シリアル化された保存されたハッシュ)を使用するのですか?

問題は「where」条件でどのように利用するかです。私はこのエラーを受け取る

@persons = Person.where([email protected]) 

::私のようにそれを使用する場合

NameError in UsersController#myfrineds 
undefined local variable or method `friends' 

私はいくつかの他のさまざまな方法を試してみましたが、それでも、私はエラーを取得します。あなたはそれを解決するために私を助けてくれますか?または、あなたがそれを実装するための良いアイデアを持っていれば教えてください(キー/値の動的ハッシュを保存する)?

答えて

0

短い回答 - できません!なぜなら、ActiveRecordはあなたの "ハッシュ"を一つの列に文字列として保存するからです。私が考えることができる唯一の方法は、.where("friends LIKE :friend", friend: 'BFF')構文を使用することです。あなたの列をインデックスに登録することを忘れないでください。

それだけでなく、mentioned in the docsです:

It's like a simple key/value store baked into your record when you don't care about being able to query that store outside the context of a single record.

+0

「friends.has_value?3」のようなものがレールコンソールでうまく動くと、Webアプリでも動作するはずです。 Ansには、このような動的リストを実装するための良い方法がありますか? @Uzbekjon –

+0

Webアプリでも動作します。 '.has_value?'は[Hash](http://ruby-doc.org/core/Hash.html#method-i-has_value-3F)メソッドであり、 'boolean'を返します。あなたの 'friends'メソッドはハッシュを返します。だからうまくいく。しかし、 '.where'メソッドにブール値を与えることはできません。あなたの場合、それは終わる: 'Person.where(真)'。 – Uzbekjon

+0

私の意図は、うまく動作する '.where(boolean_attribute:true)'のようなものでした。私はこのようなstored_attributeを使用する方法を探していましたが、値を取得するためにメソッド(has_value?など)を使用しなければならず、問題が発生します。 –

1

Uzbekjonで述べたように、は、物事のこの種のために作られていません。あなたの問題のいくつかの回避策:

  • は、(非常に遅く、テーブルのサイズに応じてことになるので注意が必要)カスタムクエリを使用します。

    @persons = Person.where('friends LIKE ? OR friends LIKE ? OR friends LIKE ? OR friends LIKE ?', "%first: #{@person.id}\n%", "%second: #{@person.id}\n%", "%third: #{@person.id}\n%", "%fourth: #{@person.id}\n%") 
    

    これは、あなたがfriendsの直列化のためにYAMLを使用を前提としてい属性(デフォルトです)。 jsonを使用した場合は、それに応じてクエリを変更する必要があります。あなたは、PostgreSQLを使用している場合

  • あなたは配列代わりの属性を使用することができます。 PostgreSQLがこのデータ型をサポートしているため、クエリのタイミングが良いでしょう。

    の移行:レコードの

    def change 
        add_column :people, :friends, :text, array: true, default: [] 
    
        # if you want to add index: 
        add_index :people, :friends, using: 'gin' 
    end 
    

    作成:

    Person.create(..., friends: [friend_id_1, friend_id_2, friend_id_3, friend_id_4]) 
    

    問い合わせ:あなたはまた、あなたのGemfileに追加する必要があり

    @persons = Person.where('? = ANY(friends)', @person.id) 
    

    gem 'postgres_ext' 
    

希望します。

+0

私はSQLiteを使用していますが、これらの問題は私にPostgreSQLへの移行を強いるでしょう!あなたの最初の解決策の問題は、IDを含むすべての結果を見つけることです。たとえば、idが1の場合、それは真ではない11,13、...を見つけます。正確な一致を見つけるためにLIKEのようなヘルパーがいますか? –

+0

@AboozarRajabiこれらの結果がすべて得られないように、カスタムクエリを更新しました。それが動作しない場合は、データベースにハッシュデータを保存する方法を見てそれに応じて調整してください。あなたのアプリがSQLiteを軽量に保つなら、PostgreSQLはすばらしいDBです。 –

+0

@AboozarRajabiもう一度、私はクエリ上の区切り文字が欠けていた - 今すぐうまくいくはずです。 –

関連する問題