В has_many: через, как правильно создать наследование объекта - PullRequest
2 голосов
/ 13 июня 2011

Я столкнулся с чем-то, что не понимаю, как моделировать с помощью ассоциаций Rails, и ни STI, ни полиморфизм, похоже, не решают эту проблему.

Я хочу иметь возможность доступа к атрибутам из таблицы соединений через коллекцию, созданную has_many: through.

В приведенном ниже коде это означает, что я хочу иметь возможность получить доступ к названию и описанию позиции комитета через объекты в коллекции .members, но, насколько я вижу, я не могу этого сделать. Я должен пройти через оригинальную таблицу соединений.

например. моделирование клуба и членов его комитета

class User < ActiveRecord::Base
  attr_accessible :full_name, 
                  :email
  has_many: committee_positions
  has_many: committees, :through => committee_positions
end

class Committee < ActiveRecord::Base
  attr_accessible :name

  has_many :committee_positions
  has_many :members, :through => :committee_positions
end

class CommitteePosition < ActiveRecord::Base
  attr_accessible :user_id, 
                  :committee_id, 
                  :member_description, 
                  :role_title

  belongs_to :committee
  belongs_to :user
end

Предположим, что каждый экземпляр позиции комитета имеет уникальное описание то есть описание относится как к члену, так и к комитету, и поэтому должно храниться в таблице соединений, а не вместе с пользователем или клубом.

, например

Committee member:  Matt Wilkins
Role:             "Rowing club president"
Description:      "Beats the heart of the rowing club to his own particular drum"

Есть ли способ получить доступ к данным в таблице соединений через коллекцию Committee.members?

Хотя активная запись дает нам этот отличный псевдоним для непосредственного обращения к участникам, похоже, нет никакого способа получить доступ к данным в объединительной таблице, которая создала коллекцию:

Я не могу сделать следующее:

rowing_committee.members.find_by_role_title('president').name

Каждый элемент в коллекции .members является объектом пользователя и, похоже, не имеет доступа ни к роли, ни к описанию, которое хранится в таблице присоединения CommitteePositions.

Единственный способ сделать это будет:

rowing_committee.committee_positions.find_by_role_title('president').user.name

Это прекрасно выполнимо, но неуклюже и бесполезно. Я чувствую, что сценарий использования достаточно общий, что я вполне могу что-то упустить.

К чему бы я хотел получить доступ через объекты в коллекции Committee.members

member
- full_name
- email
- role_title (referenced from join table attributes)
- member_description (referenced from join table attributes)

Это всего лишь маленькая вещь, но она кажется ужасной. Есть ли простой способ указать объектам-членам наследовать информацию, содержащуюся в таблице соединений?

-------------- приложение

Работая над этим, я понимаю, что могу на полпути к решению проблемы, просто определив новый класс для члена комитета и ссылаясь на него вместо пользователя в отношении has_many: through. Это работает немного лучше, но все еще довольно неуклюже

class Committee < ActiveRecord::Base
  ...

  has_many :committee_positions
  has_many :members, 
           :through => :committee_positions, 
           :class_name => 'CommitteeMember'
  ...
end


class CommitteeMember < User

  def description( committee )
    self.committees.find_by_committee_id( committee.id ).description
  end

  def role( committee )
    self.committees.find_by_committee_id( committee.id ).description
  end
end

Теперь это становится ближе, но все еще кажется неуклюжим в том смысле, что код для его использования будет:

committee = Committee.first
president_description = committee.members.find_by_title('president').description( committee )

Есть ли способ инициализировать эти объекты комитетом, на который они ссылаются?

1 Ответ

1 голос
/ 14 июня 2011

Я думаю, что вы могли бы использовать некоторые делегации здесь. В вашем классе Committee_Position:

class Committee_Position < ActiveRecord::Base
  attr_accessible :user_id, 
                :committee_id, 
                :member_description, 
                :role_title

belongs_to :committee
belongs_to :user

delegate :name, :email, :to => :user
end

чтобы вы могли делать то, что говорите:

rowing_club.committee_members.find_by_role_title('president').name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...