В моем приложении пользователь has_many tickets. К сожалению, таблица заявок не имеет user_id: она имеет user_login (это устаревшая база данных). Я собираюсь изменить это когда-нибудь, но сейчас это изменение будет иметь слишком много последствий.
Итак, как я могу создать ассоциацию "user has_many: tickets" через столбец login ?
Я попробовал следующее 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}'
Теперь это работает нормально. Очевидно, что моя проблема связана с тем, что столбец пользователей, который я пытаюсь использовать, - это строка, а не идентификатор.
Я довольно долго искал в сети ... но не мог найти подсказки.
Я бы хотел иметь возможность передать любой параметр в 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}']
Редактировать: я не могу использовать параметр: foreign_key ассоциации has_many, потому что в моей таблице пользователей есть столбец первичного ключа id, используемый в другом месте приложения.
Редактирование # 2: по-видимому, я недостаточно внимательно прочитал документацию: ассоциация has_many может принимать параметр: primary_key, чтобы указать, какой столбец является локальным первичным ключом (идентификатор по умолчанию). Спасибо, Даниэль, за то, что открыл мне глаза! Я думаю, что это отвечает на мой оригинальный вопрос:
has_many tickets, :primary_key="login", :foreign_key="user_login"
Но мне все равно хотелось бы узнать, как заставить работать ассоциацию has_many: tickets_since_subscription.