Rails 3, has_many: through и: polymorphic - нужно ли мне это делать? - PullRequest
0 голосов
/ 20 июня 2011

Хорошо, вот и все.Я не знаю, слишком ли я усложняю вещи или просто все еще настолько плохо знаком с Rails, что не понимаю основ.Что я хочу в коде sudo, так это:

User
has_many projects as owner through relationship
has_many projects as contributor through relationship
has_many projects as follower through relationship

Project
has_one user as owner through relationship
has_many users as followers through relationship
has_many users as contributors through relationship

Relationship
belongs_to user
belongs_to project

Тогда я хочу иметь следующие магические вещи:

owner = Project.owner
followers = Project.followers
contributors = Project.contributors

projects = User.projects
myprojects = User.projects... (now I'm really not sure)
followedProjects = ...
contributingProjects = ...

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

В терминах реального кода я добавил сюда то, что я считаю соответствующими частями:

class User < ActiveRecord::Base
  has_many :user_project_relationships, :as => :relateable, :class_name => "UserProjectRelationship"
  has_many :projects, :as => :owner, :through => :relateable, :class_name => "Project", :source_type => :owner
  has_many :projects, :as => :follower, :through => :relateable, :class_name => "Project", :source_type => :follower
  has_many :projects, :as => :contributor, :through => :relateable, :class_name => "Project", :source_type => :contributor
end

class Project < ActiveRecord::Base
  has_many :user_project_relationships, :as => :relateable, :class_name => "UserProjectRelationship"
  has_one :user, :as => :owner, :through => :relateable, :class_name => "User"
  has_many :users, :as => :followers, :through => :relateable, :source_type => :follower, :class_name => "User"
  has_many :users, :as => :contributors, :through => :relateable, :source_type => :contributor, :class_name => "User"
end

class UserProjectRelationship < ActiveRecord::Base
  belongs_to :user
  belongs_to :project, :polymorphic => true
end

Миграция для модели отношений:

class CreateUserProjectRelationships < ActiveRecord::Migration
  def self.up
    create_table :user_project_relationships do |t|
      t.integer :relateable_id
      t.string :relateable_type
      t.integer :project_id
      t.timestamps
    end
    add_index :user_project_relationships, [:relateable_id, :relateable_type], :name => :relateable
    add_index :user_project_relationships, :project_id
  end

  def self.down
    drop_table :user_project_relationships
  end
end

В настоящее время я получаю ошибки для таких вещей, как project.users ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :relateable in model Project

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

Заранее спасибо

Стив

1 Ответ

2 голосов
/ 20 июня 2011

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

Разделите это на отдельные модели объединения:

class User < ActiveRecord::Base

  has_many :owned_projects, :class_name => "Project", :foreign_key => :owner_id

  has_many :projects_followers
  has_many :followed_projects, :class_name => "Project", :through => :projects_followers

  has_many :projects_contributors
  has_many :contributed_projects, :class_name => "Project", :through => :projects_contributors

end

class Project < ActiveRecord::Base
  belongs_to :owner

  has_many :projects_followers
  has_many :followers, :class_name => "User", :through => :projects_followers


  has_many :projects_contributors, :foreign_key => :contributor_id
  has_many :contributors, :class_name => "User", :through => :projects_contributors

end

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

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

Должно быть намного ближе к тому, что вы хотите. Вы можете действительно сделать

project.owner
project.followers
project.contributors

и

user.owned_projects
user.followed_projects
user.contributed_projects

Это должно либо сработать, либо сблизить вас.

Я думаю, что ваша путаница возникла из-за попыток создать полиморфные отношения, которые я не считаю желательными здесь. AFAI grok, случай использования полиморфных отношений - это когда вы хотите, чтобы 1 модель была связана с любым количеством других моделей таким же образом . Это не тот случай, так как у вас есть 2 модели с 3 различными типами отношений между ними.

...