10

我是 Rails 新手,正在尝试在我的 Rails 项目中建立多对多关系。我有一个小策略,但我不确定它是否正确。

目标: 我有一张用户表和一张组表。用户可以是许多组的一部分,每个组可能有很多用户。

战略:

  1. 将用户迁移设置为具有名称:字符串
  2. 将组迁移设置为具有名称:字符串
  3. 设置连接表迁移
  4. 设置用户模型,使其具有 has_and_belongs_to_many :groups
  5. 设置组模型,使其具有 has_and_belongs_to_many :users

这会是正确的策略吗?谢谢!

Railcast 答案摘要: 对于那些感兴趣的人 - Railcast 建议您使用 has_many :through 关联,因为上述策略的限制是您无法添加额外的特定于关系的信息。

退房: http: //kconrails.com/tag/has_many/

4

1 回答 1

17

首先,我假设您有一个带有“名称”字段的用户模型和一个带有“名称”字段的组模型。

您需要用户和组之间的模型。我们称之为分组:

rails g model grouping user_name:string group_name:string

在分组模型(grouping.rb)中,您输入:

belongs_to :user  
belongs_to :group

在用户模型中:

has_many :groupings, :dependent => :destroy
has_many :groups, :through => :groupings

在组模型中:

has_many :groupings, :dependent => :destroy  
has_many :users, :through => :groupings

在用于编辑或更新用户配置文件的 _form 文件中,您输入:

<div class="field">
    <%= f.label :group_names, "Groups" %>  
    <%= f.text_field :group_names %>  
</div>

最后,用户类必须知道如何处理来自表单的信息。插入 user.rb:

  attr_writer :group_names
  after_save :assign_groups

  def group_names
    @group_names || groups.map(&:name).join(' ')
  end

  private

  def assign_groups
    if @group_names
      self.groups = @group_names.split(/\,/).map do |name|
        if name[0..0]==" "
          name=name.strip
        end
        name=name.downcase
        Group.find_or_create_by_name(name)
      end
    end
  end

assign_groups 删除空格并将所有单词小写,因此您不会有多余的标签。

现在,您可以在用户个人资料的显示文件中显示用户的组:

<p>Groups:
  <% @user.groups.each do |group|%>
    <%= group.name %>
   <% end %>
</p>

希望,这有帮助。

于 2012-04-21T18:43:27.230 回答