Имеет множество обратных вызовов через ассоциацию с несколькими ассоциациями, использующими одну и ту же таблицу соединений - PullRequest
0 голосов
/ 04 февраля 2012

Так что это может быть очень плохой формой. Я относительно новичок в рельсах. Я не уверен.

У меня есть модель проекта, и я хочу, чтобы было много владельцев (которые могут читать и писать все) и много соавторов (которые могут читать и писать некоторые вещи).

В моем файле project.rb у меня есть:

  has_many :project_user_relationships, :dependent => :destroy
  has_many :collaborators, :through => :project_user_relationships, :source => :user

  has_many :project_owners_relationships, :class_name => "ProjectUserRelationship", :foreign_key => "project_id", 
           :before_add => Proc.new { |p,owner_r| owner_r.owner = true }, :conditions => "`project_user_relationships`.owner = true"
  has_many :owners, :through => :project_owners_relationships, :source => :user

Так что это работает достаточно хорошо. Если я добавлю нового владельца, этот пользователь также станет соавтором, чего я и хочу. Проблема, которую я не знаю, как решить, если я добавлю пользователя, который уже является соавтором, в качестве владельца, я получу две записи в таблице соединений. Я хотел бы просто изменить запись, которая уже есть. Как мне это сделать?

1 Ответ

1 голос
/ 04 февраля 2012

Вот модель данных, которую я бы предложил для этого:

class Project < ActiveRecord::Base
    has_many :memberships, :dependent => :destroy
    ...
end

class Membership < ActiveRecord::Base
    belongs_to :project
    belongs_to :user
    ...
end

class User < ActiveRecord::Base
    has_many :memberships, :dependent => :destroy
    has_many :projects, :through => :memberships
    ...
end

И тогда таблица членства будет иметь следующие атрибуты:

:id
:user_id
:project_id
:is_owner (boolean)

Область действия, определенная для класса членства:

scope :owner, where("is_owner")

И специальный метод для пользовательских экземпляров:

def owned_projects
    memberships.owner.includes(:projects).inject([]) {|array, m| array << m.project; array}
end

позволит вам получать проекты, принадлежащие пользователю, с помощью вызова user.owned_projects.

И простовызов user.projects для просмотра проектов пользователя, с которыми они либо сотрудничают, либо владеют.

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

Эта модель данных используется в этом проекте , за исключением s / Project / Group /, и есть некоторые дополнительные функции для обработки приглашения пользователей в Project.

Это не отвечает на ваш «реальный вопрос», но я думаю, что отчасти проблема заключается в том, что модель данных, где соавторы являются владельцами, хранятся в одной таблице, чтобы минимизироватьИзбыточности и необходимость управления двумя отдельными таблицами.

...