创建"多对多"的问题关系

时间:2016-12-15 10:09:57

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

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

我检查了APIDock并做了以下事情:

  1. 指定杂志与用户之间的关系
  2. 模型/ magazine.rb

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

    模型/ 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
      
    2. 然后我运行了迁移

      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>
        
      2. 但是,当我保存新杂志时,用户无法保存,并且&#34; magazines_user仍为空。

        编辑1

        这是一个自动生成的控制器,因为我使用scaffold命令来创建它。除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
        

        我忘记了任何一步吗?

1 个答案:

答案 0 :(得分: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>

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

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

为了看到它有效,我在magazin show视图中添加了这个:

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

当然我添加了#34; has_and_belongs_to_many&#34;正如您在用户和杂志模型中所做的那样。

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

此外,我强烈建议您查看the simple_form gem。它有一些很好的方法可以轻松处理关联(例如has_and_belongs_to_many),如下所示:<%= f.association :users, collection: User.all_except(current_user).order(:username) %>