2010-09-24 3 views
0

У меня есть ассоциация has_one, отражающая объекты другой ассоциации. У меня есть Project, в котором есть много ProjectUsers, которые связывают проекты и пользователей. Один из этих ProjectUsers является авторитетным. Проблема в том, что has_one и has_many используют один и тот же внешний ключ для project_users. Вот базовая идея моделей.Переопределение метода присваивания для has_one

class Project < ActiveRecord::Base 
    has_many :project_users, :class_name => 'ProjectUser', :foreign_key => 'project_id' 
    has_one :authoritative_user, :class_name => 'ProjectUser', :foreign_key => 'project_id', :conditions => {:authoritative => true} 
end 

class ProjectUser < ActiveRecord::Base 
    belongs_to :project 
    belongs_to :user 
    # has a boolean column 'authoritative' 
end 

Что я хотел бы, чтобы иметь возможность позвонить, это что-то типа.

project = Project.new 
project_user = ProjectUser.new 
project.project_users << project_user 
project.authoritative_user = project_user 
other_project_user = ProjectUser.new 
project.project_users << other_project_user 
project.authoriative_user = other_project_user 

Где authoritative_user = обновит пользователю проекта, чтобы иметь авторитетное быть установлен так, и сделать предыдущий авторитетный пользователь имеет авторитетное значение ЛОЖЬ. Еще одна проблема, с которой я сталкиваюсь, заключается в том, что во второй раз, когда я устанавливаю authoritative_user в проекте, project_id на предыдущем ProjectUser получает значение nil, и поэтому он больше не связан с Project_users проекта.

Я не уверен, что я просто делаю это совершенно неправильно, или если я просто что-то пропустил.

ответ

3
class Project < ActiveRecord::Base 
    has_many :project_users 
    has_many :users, :through => :project_users 

    belongs_to :authoritative_project_user, :class_name => 'ProjectUser' 
    has_one :authoritative_user, :through :authoritative_project_user 
end 

class ProjectUser < ActiveRecord::Base 
    belongs_to :project 
    belongs_to :user 

    has_one :project_as_authorized_user 
end 

, то просто пусть отношения has_one project_as_authorized_user NIL ваш belongs_to authorized_project_user

1

Лично я, вероятно, хотел бы упростить/разделить проблемы. Вот пример (примечание: непроверенное):

class Project < ActiveRecord::Base 
    has_many :project_users 
    has_many :users, :through => :project_users 
    has_one :authoritative_user 
end 

class ProjectUser < ActiveRecord::Base 
    belongs_to :project 
    belongs_to :user 
end 

class AuthoritativeUser < ActiveRecord::Base 
    belongs_to :project 
    belongs_to :user 

    validates_uniqueness_of :user_id, :scope => :project_id 
end 

По существу, я вспыхиваю атрибут вашей ProjectUser модели authoritative_user в его собственном. Очень просто, чисто и не очень интересно.

Возможно, вы создали несколько удобных методов, таких как has_authoritative_user? и update_authoritative_user в вашей модели Project.

Я уверен, что вы получите несколько лучших предложений.

Надеюсь, это поможет!

+0

Мне нравится это решение, если authoritative_user не должен быть изменяемым. Я мог бы даже увидеть, что это работает, если в ProjectUser не было других столбцов для описания пользовательских отношений Project <=>, и поэтому пользователь на AuthoritativeUser мог бы измениться, чтобы определить, кто был авторитетным пользователем, но, к сожалению, есть дополнительные данные. Я мог бы абстрактно выделить все дополнительные метаданные в отдельную модель и просто связать это с ProjectUser/AuthoritativeUser. Я говорю, что потенциально, поскольку для этого случая понадобится массивный страшный рефактор 2-летнего кода. – lambdabutz

+0

Если я чего-то не хватает, authoritative_user, безусловно, может измениться (но может быть только один). Кроме того, нет причин, по которым модель ProjectUser не может иметь дополнительных атрибутов. В конце концов, это по существу, почему существует связь 'has_many: through'. – Brian

Смежные вопросы