【问题标题】:Rails 3, has_many :through and :polymorphic - Should I need to do this?Rails 3,has_many :through 和 :polymorphic - 我需要这样做吗?
【发布时间】:2011-06-19 23:39:22
【问题描述】:

好的,就到这里。我不知道我是不是把事情复杂化了,或者我对 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 之类的错误

我觉得我在这里太荒野了,无法真正得到我想要的东西,也许依靠神奇的铁轨来做更多的事情。任何关于最佳路径的指导将不胜感激。

提前致谢

史蒂夫

【问题讨论】:

    标签: ruby ruby-on-rails-3 associations has-many-through has-many-polymorphs


    【解决方案1】:

    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 种不同类型的关系。

    【讨论】:

    • 感谢您的回复。我认为这听起来像我想要的,但我想这感觉像是在数据库级别的重复。我来自多年的 PHP/MySQL 工作,我会使用一个单一的连接表来处理双方的关系。如:用户——Users2Projects——项目。这两种关系成为孤儿有什么风险吗?这取决于应用程序来执行吗?我在这里添加两个关系来服务多对多的每一方。如果一个被删除而没有另一个,你最终不会关注一个项目,但仍然被视为项目方面的追随者。
    • 你好。无法实现这一点并对其进行测试符合我的预期。当我尝试关联用户以关注项目时出现此错误:project.project_followers &lt;&lt; user ActiveRecord::AssociationTypeMismatch: ProjectFollower(#2155362360) expected, got User(#2158321740)
    • 1) 你对孤儿的看法是对的——它也由 Rails 处理——你想将 :dependent => :destroy 键添加到 projects_followers 和 projects_contributors。 2) projects_followers 和 projects_contributors 是为了在 has_many_through 关系中保持完整性,如果您需要为这些关系添加额外的键(某人成为贡献者多久了?他们做了多少贡献?等等),它们很有用,但是你也可以经常忽略它们。您收到该错误的原因是您应该直接访问关注者协会:project.followers
    猜你喜欢
    • 1970-01-01
    • 2019-03-04
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    相关资源
    最近更新 更多