Rails 3、has_many :through 和 :polymorphic - 我需要这样做吗?

发布于 2024-11-16 05:23:43 字数 2866 浏览 3 评论 0原文

好的,就这样吧。我不知道我是否让事情变得过于复杂,或者我是否对 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 之类的错误在模型项目中,

我觉得自己太身处荒野,无法真正得到我想要的东西,也许依靠神奇的轨道可以做更多的事情。任何关于最佳路径的指导将不胜感激。

预先感谢

史蒂夫

Ok so here goes. I don't know if I'm over complicating things or if I'm just still so new to Rails that I don't understand the basics. What I want in sudo code is this:

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

Then I'm wanting to have the following magical things:

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

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

So in writing that down I can see that there is another gap in my understanding of this model. The users can have the role of owner, follower or contributor or any combination of all three.

In terms of real code I have added here what I think is the relevant parts:

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

The migration for the relationships model is:

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

Currently I get errors for things like project.users ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :relateable in model Project

I feel like I'm too in the wilderness here to really get what I want, and maybe relying on magical rails to do more than it does. Any guidance on the best path would be greatly appreciated.

Thanks in advance

Steve

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鲜肉鲜肉永远不皱 2024-11-23 05:23:43

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

Rails can do alot, but I think instead you're trying to make the Relationship model do too much. Each of those are a different kind of relationship, so I think try to keep them so.

Split that up into separate join models:

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

Should be a lot closer to what you want. You can then indeed do

project.owner
project.followers
project.contributors

and

user.owned_projects
user.followed_projects
user.contributed_projects

That should either work, or get you pretty close.

I think your mixup came from trying to make a polymorphic relationship, which I don't think is desireable here. AFAI grok, the use case for polymorphic relationships is when you want 1 Model to be related to Any number of other models in the same way. That's not the case here, as you have 2 models with 3 different types of relationships between them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文