【问题标题】:Issues with creating a "many-to-many" relation创建“多对多”关系的问题
【发布时间】:2017-04-30 21:33:57
【问题描述】:

我正在尝试做一个简单的任务:我创建了一个“杂志”脚手架,但我希望它具有特定的关系:用户可以参与杂志的创建/编辑,这可能需要几个用户创建杂志。

我检查了 APIDock 并执行了以下操作:

  1. 指定杂志和用户之间的关系

model/magazine.rb

class Magazine < ApplicationRecord
  mount_uploader :thumbnail, ThumbnailUploader
  has_and_belongs_to_many :users
end

model/user.rb

class User < ApplicationRecord
  has_and_belongs_to_many :magazines

  # More code...
end
  1. 创建了一个迁移以添加一个表来链接两个模型

    class ManyToMany < ActiveRecord::Migration[5.0]
        def change
    
            create_table :magaziness_users, :id => false do |t|
              t.integer :user_id
              t.integer :magazine_id
            end
    
        add_index :magazines_users, [:magazine_id, :user_id]
      end
    end
    

然后我运行迁移

  1. 将曾经记录到数据库中的所有用户的列表添加到创建下拉列表

    <div class="field">
      <%= f.label :users %>
      <%= f.select :users, User.all_except(current_user).collect {|u| [u.username, u]}, {prompt: 'Add a creator?'}, { :multiple => true, :size => 3 } %>
    </div>
    

但是,当我保存新杂志时,用户没有被保存,并且“magazines_user 仍然为空。

编辑 1

这是一个自动生成的控制器,因为我使用脚手架命令来创建它。除了 set_magazine 函数,我没有碰任何东西,我在其中添加了 Friendly_Id

class MagazinesController < ApplicationController
  before_action :set_magazine, only: [:show, :edit, :update, :destroy]

  def index
    @magazines = magazine.all
  end

  def show
  end

  def new
    @magazine = magazine.new
  end

  def edit
  end

  def create
    @magazine = magazine.new(magazine_params)

    if @magazine.save
      redirect_to @magazine, notice: 'magazine was successfully created.'
    else
      render :new
    end
  end

  def update
    if @magazine.update(magazine_params)
      redirect_to @magazine, notice: 'magazine was successfully updated.'
    else
      render :edit
    end
  end

  def destroy
    @magazine.destroy
    redirect_to magazines_url, notice: 'magazine was successfully destroyed.'
  end

  private
    def set_magazine
      @magazine = magazine.friendly.find(params[:id])
    end

    def magazine_params
      params.require(:magazine).permit(:titre, :description, :apercu, :users)
    end
end

我是不是忘记了什么步骤?

【问题讨论】:

  • 请发布您的控制器代码。
  • 我添加了控制器
  • 我从未将这种方法用于多对多关系......更好的方法是使用“有很多通过”......在这里阅读:guides.rubyonrails.org/…
  • 问题是我真的不需要其他实体,我只需要说明谁参加了哪些杂志,哪些杂志可以在谁的个人资料上找到..
  • 您的迁移中没有错字:create_table :magaziness_users 吗?同样奇怪的是,在您的控制器中,您的“magazine.new”不应该是:Magazine.new?

标签: ruby-on-rails model many-to-many entity-relationship


【解决方案1】:

所以这是我的代码工作的答案:

我做了两个脚手架:

rails generate scaffold user username:string email:uniq password:digest
rails generate scaffold magazine title:string description:text preview:string

然后将此添加到杂志迁移中:

create_table :magazines_users, id: false do |t|
  t.belongs_to :magazine, index: true
  t.belongs_to :user, index: true
end

在我的表单中,我添加了:

<div class="field">
  <%= f.label :users %>
  <%= f.select :user_ids, User.all.collect { |u| [u.username, u.id] }, {include_blank: true}, {multiple: true} %>
</div>

在我的杂志控制器中,我只修改了杂志参数:

def magazine_params
  params.require(:magazine).permit(:title, :description, :preview, :user_ids => [])
end

为了看看它是否有效,我在杂志展示视图中添加了这个:

<p>
  <strong>Users:</strong>
  <%= @magazine.users.map(&:username).join(" - ") %>
</p>

当然,我添加了“has_and_belongs_to_many”,就像您在用户和杂志模型中所做的那样。

就是这样:) 用 Rails 5 测试,它工作得很好。 :)

我也强烈建议你看看the simple_form gem。它有一些很好的方法来轻松处理关联(如 has_and_belongs_to_many),如下所示:&lt;%= f.association :users, collection: User.all_except(current_user).order(:username) %&gt;

【讨论】:

  • 我对您的建议有疑问:当我尝试加载杂志#new 时,我得到 undefined method 'users_ids' for #&lt;Magazine:0x0000000de49eb0&gt;.. 我不知道这是否与迁移或其他有关
  • 为什么会有“users_ids”?看看你的表格,应该是“user_ids”:)
  • 你完全正确!!但是现在我遇到了另一个问题,这是我之前尝试创建多对多关联时遇到的问题:ActiveRecord::AssociationTypeMismatch (User(#139695920) expected, got NilClass(#10121780))
  • 仔细检查您的表格。检查还在 Rails 日志中发送的参数。 Rails 似乎无法找到链接到杂志的用户。也许您的表格中缺少u.id?当我的解决方案奏效时,您必须深入研究并尝试找出为什么它对您不起作用。只有这样你才能学到一些东西。否则你将很难重做这种关联(并且“has_many :through”并不容易)。
  • 好吧,我工作了(我仍然不明白为什么:D),因为我调整了我的 f.select 表单而不是复制/粘贴你的表单,即使我认为这是同一件事(我有一个提示而不是“include_blank”)。现在可以了,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 2020-04-10
  • 2021-09-14
  • 2015-07-09
相关资源
最近更新 更多