Каков класс ассоциации, основанной только на атрибуте внешнего ключа? - PullRequest
13 голосов
/ 13 июля 2010

Short: у меня есть атрибут внешнего ключа и я хочу знать, каков класс (или справочная таблица) этого поля внешнего ключа.

Контекст:

дано 2 таблицы: users(id, [other fields]) и issues(id, user_id, assigned_to, [other fields])

Вот моя активная запись о проблеме (извлечены не относящиеся к делу части)

class User < ActiveRecord::Base
  ...
end
class Issue < ActiveRecord::Base
  belongs_to :user
  belongs_to :assigned_user, :foreign_key => 'assigned_to', :class_name => 'User'
  ...
end

Я хочу сделать удобочитаемую запись в журнал изменений. например при смене назначенного пользователя я хочу получить следующее сообщение: Assigned to is changed from Otto to Zoltan. ActiveRecord имеет функцию changes, которая является хорошей отправной точкой, но дает мне только ссылочные идентификаторы. Чтобы перевести на имена, мне нужно прочитать пользователя по идентификатору.

Для ассоциации :user это довольно легко, потому что я должен следовать только соглашениям. Но как получить ту же информацию для атрибута assigned_to (я хочу сделать общее решение)? Можно ли выяснить, есть ли у нас ассоциация для данного атрибута? Можем ли мы извлечь класс этой ассоциации?

Ответы [ 2 ]

32 голосов
/ 13 июля 2010

Во-первых, вы можете использовать reflect_on_association, чтобы получить метаданные для желаемой ассоциации.Затем из его результата (который является MacroReflection потомком) вы можете узнать класс:

reflection = Issue.reflect_on_association(:assigned_user)
reflection.class # => ActiveRecord::Reflection::AssociationReflection
reflection.class_name # => 'User'

См. Документы здесь и там .

3 голосов
/ 13 июля 2010

Спасибо.Вот окончательное решение для конкретной задачи (для обучения):

  def textalize_changes
    if changed?
      r = ""
      changes.keys.each do |k|
        r << "#{k.humanize} changed "
        r << "from `#{translate(k,changes[k][0])}` " 
        r << "to `#{translate(k,changes[k][1])}`"
        r << "<br/>"
      end
      r
    end
  end

  def translate(attr_name, attr_value)
    ass = self.class.reflect_on_all_associations(:belongs_to).reject{|a| attr_name != a.primary_key_name}
    if 1 == ass.length and !attr_value.blank?
      obj = ass[0].klass.find(attr_value)
      obj.send(:name)
    else
      attr_value
    end
  end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...