不确定我的应用需要哪种模型关联方法

时间:2015-08-25 18:00:38

标签: ruby-on-rails ruby

我到目前为止:

class Organization < ActiveRecord::Base
    belongs_to :user
    has_many :events
    has_many :vips
end

class Event < ActiveRecord::Base
  belongs_to :organization
  has_many :vips
end

class Vip < ActiveRecord::Base
    belongs_to :organization
    belongs_to :event
end

我的新活动表格

<%= form_for [@organization, @event] do |f| %>
    <p>
        <%= f.label :when %>
        <%= f.date_select :when %>
    </p>
    <p>
        <%= f.label :name %>
        <%= f.text_field :name %>
    </p>
    <p>
        <%= f.label :vip %>
        <%= f.select :vip_id, options_for_select(@organization.vips.all.map {|v| [v.name, v.id]}) %>
    </p>
    <p>
        <%= f.submit %>
    </p>
<% end %>

我的模型在控制台中的样子:

<Organization id: 1, name: "Test Org", created_at: "2015-08-25 04:46:03", updated_at: "2015-08-25 04:46:03", user_id: 1>

<Event id: 1, when: "2015-08-25 00:00:00", organization_id: 1, created_at: "2015-08-25 04:47:43", updated_at: "2015-08-25 04:47:43", name: "John's Event", vip_id: 1>

<Vip id: 1, name: "Captain", created_at: "2015-08-25 04:46:23", updated_at: "2015-08-25 06:51:47", organization_id: 1>

注意:我运行了“rails generate migration add_vip_id_to_events vip:references”我之所以这样做是因为我希望每个组织的少量vips能够附加到大量事件中。我希望每个事件都能根据vip_id列知道哪些vips附加到它上面。

我想要完成的事情:

在我的应用程序中,我有组织,事件和Vip模型。在我的'组织#show'页面上,我希望为特定组织举办所有活动,以便有一个日期(例如“2015年9月1日星期一”,“2015年9月2日星期二”和“星期三,9月” 3 2015“)作为表格标题,然后该日期的所有事件将被列为”事件名称,由事件Vip,事件位置,事件时间给出。“

在组织中,我也希望有Vips,在组织内有自己的'Vip#Show'页面。并且,当您填写事件表单时,您将能够从现有组织视图中选择与该事件(以及许多其他事件)相关联的VIP / vip。

问题:

如果我去控制台,并试图找到附加到活动的贵宾,我会做以下事情:

@organization = Organization.find(1)
@event = @organization.events.first
@event.vips.first

并返回=&gt;零

好的,现在我运行一个rails迁移,它将一个event_id列添加到vips,并在控制台中手动填充它,以便它指向组织的第一个事件(event_id = 1),当我运行相同的代码时,我明白了:

@organization = Organization.find(1)
@event = @organization.events.first
@event.vips.first
=> #<Vip id: 1, name: "John", created_at: "2015-08-25 04:46:23", updated_at: "2015-08-25 06:51:47", organization_id: 1, event_id: 1>

这是一个问题,因为我的vips只能与一个事件相关联。我需要它们能够与许多事件相关联,以便我可以通过块代码访问它们,例如

<% @events = @organization.events.all %>
<% @events.each do |event| %>
  <%= event.name %>
  <% event.vips.each do |vip| %>
    <%= vip.name %>
  <% end %>
<% end %>

2 个答案:

答案 0 :(得分:1)

听起来你可能想要

class Organization < ActiveRecord::Base
  has_many :vips

class Event
  has_many :event_vips
  has_many :vips, :through => :event_vips

class EventVip < ActiveRecord::Base
  belongs_to :event
  belongs_to :vip

class Vip < ActiveRecord::Base
  belongs_to :organization
  has_many :events_vips
  has_many :events, :through => :event_vips

这将使vips成为单个组织的孩子,并且能够连接多个事件。

答案 1 :(得分:0)

听起来你正在尝试创建多对多关系,而不是像现在这样创建一对多关系。如果您查看导轨指南,他们会详细解释here。基本思想是有第三个表来定义事件和vip之间的所有关系。该表通常有一个event_id列和一个vip_id列。表中的每一行都是一个关联,因此您可以为同一个vip或事件列出多个关联。

这样您就可以拨打event.vips甚至vip.events

实际上有两个选项可以获得多对多关系,您可以使用has_and_belongs_to_manyhas_many :through。这些差异也在指南中列出,但总结一般的想法是,如果您需要将附加信息或方法附加到关系本身,则可以使用has_many :through。在这种情况下,它被视为自己独立的实体或模型。如果你没有这个,并且只想关联你已经拥有的两个模型,那么has_and_belongs_to_many更容易使用,只需要数据库中的表。

<强> has_and_belongs_to_many

class Event < ActiveRecord::Base
  has_and_belongs_to_many :vips
end

class VIP < ActiveRecord::Base
  has_and_belongs_to_many :events
end

has_many:通过

class Event < ActiveRecord::Base
  has_many :event_vip_list
  has_many :vips, through: :event_vip_list
end

class Vip < ActiveRecord::Base
  has_many :event_vip_list
  has_many :events, through: :event_vip_list
end

class EventVipList < ActiveRecord::Base
  belongs_to :event
  belongs_to :vip
end