Rails4复杂嵌套has_many:通过,需要帮助才能找到“rails way”

时间:2013-12-05 16:31:48

标签: activerecord ruby-on-rails-4 has-many-through

我的目标是让用户能够提名客人谈论某个主题,但复杂的是,他们(或用户)可以提供许多“链接”,以支持此提名客人的选择。

所以我的表格,最简单的形式,如下所示:

create_table "topics", force: true do |t|
    t.string   "name"
end
create_table "guests", force: true do |t|
    t.string   "name"
end
create_table "topic_guests", force: true do |t|
    t.integer  "topic_id"
    t.integer  "guest_id"
    t.integer  "user_id" #(who nominated this guest)
end
create_table "links", force: true do |t|
    t.integer  "user_id"
    t.integer  "topic_id"
    t.integer  "guest_id"
    t.string   "url"
end

我很难获得使用has_many的链接:through,因为:through是另一个has_many的连接表:through(whew)。

使用此配置添加主题和来宾非常有用:

class Topic < ActiveRecord::Base

  belongs_to :user

  has_many :topic_guests, :dependent => :destroy  
  has_many :guests, :through => :topic_guests

end

class Guest < ActiveRecord::Base
  has_many :topic_guests, :dependent => :destroy  
  has_many :topics, :through => :topic_guests
end

在向已提名的访客添加链接时,链接模型很简单:

class Link < ActiveRecord::Base
  belongs_to :guest
  belongs_to :topic
  belongs_to :user
end

但我似乎无法添加指定客人的链接。目标是做这样的事情(输入这个让我意识到为什么这是一个艰难的任务,以“铁路方式”)

@topic.guests.find(params[:guest_id]).links << current_user.links.build(link_params)

1 个答案:

答案 0 :(得分:0)

嗯,我真的建议你坐下来,真正考虑模型之间的关系。有时,在纸上绘制数据库有助于了解模型如何相互作用。有很多方法可以重构您拥有的数据。由于它实际上有点复杂,我会列出一些选项。

使您的链接具有多态性

这似乎是第一个跳出来的人,你应该让你的链接成为多态关系。这是一个railscast(惊人的资源),http://railscasts.com/episodes/154-polymorphic-association-revised?view=asciicast

使用您的模型,您可以通过几种方式进行设置。例如,来宾和用户可以将多个链接作为多态,并且链接始终具有主题ID。这取决于你想要如何做数据。迁移和模型看起来像这样

class CreateLinks < ActiveRecord::Migration
  def change
    create_table :links do |t|
      t.references :authorable, index: true  # ex: user_id or guest_id
      t.string :authorable_type  # ex: user or guest

      t.references :topic, index: true

      t.string :url

      t.timestamps
    end
  end
end

模型看起来像这样,

link.rb

class Link < ActiveRecord::Base
  belongs_to :authorable, :polymorphic => true

  belongs_to :topic
end

topic.rb

class Topic < ActiveRecord::Base
  has_many :links
end

user.rb

class User < ActiveRecord::Base
  has_many :links, :as => :authorable
end

guest.rb

class Guest < ActiveRecord::Base
  has_many :links, :as => :authorable
end

这只是一个例子,你可以很容易地反过来说并且说链接属于用户并且使他们关于多态的链接。这进入了我的下一步,

您可以将访客设为用户

这不是一项要求,但它可以帮助您将所有客户一起移除,并让他们成为用户的角色。正如你在这里所提供的,我会让客人分开以简化并使用has_many与客人和用户的关系,内部表被称为提名。

有很多通道的原因是你可能想要保存该关系的数据,例如它可能有一个名为success的布尔字段,当成功提名时会变为true。这是一个很好的链接,解释了很多,http://blog.hasmanythrough.com/2007/1/15/basic-rails-association-cardinality

有很多通过这里给你很大的灵活性

现在你可能想要使用的这个特定例子的另一个原因是,你可以说提名属于一个主题,主题有多个提名。我认为这是一种很好的关联数据的方式,但它实际上取决于您比我更了解的数据之间的深层次互动。

此应用中是否仅使用与提名和主题相关的链接?在这方面,客人只能被提名一个主题吗?链接也可以用于多个主题吗?这些都是您需要问自己的好问题。我只能提出建议,但这会假设你比我更了解的事情,因为你更了解应用程序。

我可以继续研究应用程序有多大效果数据结构,但继承了我使用的数据之间的最终联系:

  1. 用户通过提名有很多客人
  2. 客人通过提名获得了许多用户
  3. 提名属于主题
  4. 主题有很多提名
  5. 提名有很多链接
  6. 链接属于提名
  7. 链接是多态的,谁创建了它们(在我的例子中可以使用)
  8. 而且我认为这足以涵盖你的问题。祝你好运!