我正在尝试创建一个Wiki风格的应用程序。现在的基本模型是User和Wiki。她创建的用户has_many
Wiki,以及用户的Wiki belongs_to
。到目前为止这么容易。现在是复杂的。
我希望Wiki能够拥有无限制的合作用户。这区分了Wiki的所有者和协作者,但两者都是用户。我认为这对于Has Many Through关系来说是个好例子,所以我创建了一个连接表:Collaboration。
以下是我的迁移生成器(我没有偏离)。第一个维基:
rails g model Wiki body:text title:string owner_id:integer
然后用户:
rails g model User name:string
然后协作:
rails g model Collaboration wiki_id:integer collaborator_id:integer
我的想法是,我应该可以致电wiki.owner
和wiki.collaborators
,以及user.owned_wikis
和user.collaborated_wikis
。通过硬编码我自己的方法,我已经完成了大部分工作。也就是说,这非常有效:
class User < ActiveRecord::Base
def owned_wikis
Wiki.where(owner_id: id)
end
def collaborations
Collaboration.where(collaborator_id: id)
end
def collaborated_wikis
collaborations.wikis
end
end
class Collaboration < ActiveRecord::Base
def self.collaborators
User.where(id: pluck(:collaborator_id))
end
def self.wikis
Wiki.where(id: pluck(:wiki_id))
end
def wiki
Wiki.where(id: wiki_id)
end
def collaborator
User.where(id: collaborator_id)
end
end
class Wiki < ActiveRecord::Base
def owner
User.where(id: owner_id)
end
def collaborations
Collaboration.where(wiki_id: id)
end
def collaborators
collaborations.collaborators
end
end
我可以把它留在那里,但这会使某些事情(比如,wiki.collaborators << User.create(name: 'Whatever')
难以/不可能。我喜欢用AR关系做这一切,但我遇到了麻烦。这就是我的地方:
class User < ActiveRecord::Base
has_many :owned_wikis, class_name: 'Wiki', foreign_key: 'owner_id'
has_many :collaborations, foreign_key: 'collaborator_id'
has_many :collaborated_wikis, class_name: 'Wiki', through: :collaborations
end
class Collaboration < ActiveRecord::Base
belongs_to :wiki
belongs_to :collaborator, class_name: 'User'
# The issue here is that relations of Collaborations don't respond to `collaborators` or `wikis`
end
class Wiki < ActiveRecord::Base
belongs_to :owner, class_name: 'User'
has_many :collaborations
has_many :collaborators, class_name: 'User', through: :collaborations
end
它正在做一些基本的事情user.owned_wikis
,wiki.owner
,w.collaborations
等,但不是 w.collaborators
或{{1} }。
对于这两个人,我得到了这些错误。 u.collaborated_wikis
:
w.collaborators
和 User Load (0.9ms) SELECT "users".* FROM "users" INNER JOIN "collaborations" ON "users"."id" = "collaborations"."collaborator_id" WHERE "collaborations"."wiki_id" = $1 [["wiki_id", 1]]
PG::UndefinedFunction: ERROR: operator does not exist: integer = character varying
LINE 1: ...sers" INNER JOIN "collaborations" ON "users"."id" = "collabo...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT "users".* FROM "users" INNER JOIN "collaborations" ON "users"."id" = "collaborations"."collaborator_id" WHERE "collaborations"."wiki_id" = $1
:
u.collaborated_wikis
任何想法如何更好地做到这一点?我希望有一个完全成熟的多任务关系,以便我可以ActiveRecord::HasManyThroughSourceAssociationNotFoundError: Could not find the source association(s) :collaborated_wiki or :collaborated_wikis in model Collaboration. Try 'has_many :collaborated_wikis, :through => :collaborations, :source => <name>'. Is it one of :wiki or :collaborator?
或wiki.collaborators << user
。在here描述的那种,但所有这些奇怪的重命名扭结。
任何想法如何将其串起来?
已解决 - 以下答案产生的最终版本:
user.collaborated_wikis << wiki
答案 0 :(得分:2)
提供:来源选项
has_many :collaborated_wikis, through: :collaborations, source: :wiki
has_many :collaborators, through: :collaborations, source: :colaborator
但是我只是将colaborator_id更改为Collaboration模型上的user_id,因为您已经有了#34; Collaborate&#34;此模型本身的命名空间,这将允许您更多地使用rails默认值。