私のアプリケーションでは、ユーザーは has_many チケットを持っています。残念ながら、チケット テーブルには user_id がなく、user_login があります (レガシー データベースです)。いつか変更する予定ですが、今のところ、この変更には多くの影響があります。
では、ログイン列を介して「user has_many :tickets」関連付けを作成するにはどうすればよいでしょうか?
次の finder_sql を試しましたが、うまくいきません。
class User < ActiveRecord::Base
has_many :tickets,
:finder_sql => 'select t.* from tickets t where t.user_login=#{login}'
...
end
奇妙なエラーが発生します:
ArgumentError: /var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:402:in `to_constant_name': Anonymous modules have no name to be referenced by
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:2355:in `interpolate_sql'
from /var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:214:in `qualified_name_for'
from /var/lib/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:477:in `const_missing'
from (eval):1:in `interpolate_sql'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_proxy.rb:95:in `send'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/association_proxy.rb:95:in `interpolate_sql'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/has_many_association.rb:143:in `construct_sql'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations/has_many_association.rb:6:in `initialize'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations.rb:1032:in `new'
from /var/lib/gems/1.8/gems/activerecord-2.0.2/lib/active_record/associations.rb:1032:in `tickets'
from (irb):1
このfinder_sqlも試しました(ログインを二重引用符で囲みます):
:finder_sql => 'select t.* from tickets t where t.user_login="#{login}"'
しかし、それは同じように失敗します (とにかく、それが機能したとしても、SQL インジェクションに対して脆弱です)。
テスト データベースで、チケット テーブルに user_id 列を追加し、次の finder_sql を試しました。
:finder_sql => 'select t.* from tickets t where t.user_login=#{id}'
これで問題なく動作します。どうやら、私の問題は、使用しようとしているユーザー列がIDではなく文字列であるという事実に関係しています。
かなり長い間ネットを検索しました...しかし、手がかりは見つかりませんでした。
任意のパラメーターを finder_sql に渡して、次のように記述できるようにしたいと考えています。
has_many :tickets_since_subscription,
:finder_sql => ['select t.* from tickets t where t.user_login=?'+
' and t.created_at>=?', '#{login}', '#{subscription_date}']
編集: has_many 関連付けの :foreign_key パラメータを使用できません。ユーザー テーブルには、アプリケーションの他の場所で使用される id 主キー列があるためです。
編集#2:ドキュメントを十分に読んでいないようです.has_many関連付けは、:primary_keyパラメーターを使用して、ローカルの主キー(デフォルトID)である列を指定できます。ダニエル、目を開けてくれてありがとう!私はそれが私の元の質問に答えていると思います:
has_many tickets, :primary_key="login", :foreign_key="user_login"
しかし、 has_many :tickets_since_subscription 関連付けを機能させる方法を知りたいです。