在我的应用程序中,用户 has_many 票。不幸的是,tickets 表没有 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 参数,因为我的 users 表确实有一个 id 主键列,在应用程序的其他地方使用。
编辑#2:显然我没有足够彻底地阅读文档:has_many 关联可以采用 :primary_key 参数来指定哪一列是本地主键(默认 id)。谢谢丹尼尔让我大开眼界!我想它回答了我原来的问题:
has_many tickets, :primary_key="login", :foreign_key="user_login"
但我仍然很想知道如何使 has_many :tickets_since_subscription 关联工作。