如何在 Ruby 中的两个模型之间建立模型关联。或者如何从一个模型中获取数据并将其用于另一个模型?

How to make model associations between two models in Ruby. Or How to take data from one model and use it in another model?

所以我创建了两个模型,一个 "Course" 和一个 "Section" 带有脚手架,并且需要部分在下拉菜单中显示课程,该菜单反映在课程模型中创建的任何课程并使用它在部分中创建。我已经能够获得显示从 "Course" 创建的课程的下拉菜单,但是当我创建新部分时,课程显示为空白。课程有名称、部门、编号和学分。部分有学期、编号、课程和房间号。

我为制作下拉菜单所做的修改是(在 _form.html.erb 的部分视图中)

  <div class="field">
  <%= form.label "Courses", class: 'courses'%>
  <%= form.collection_select(:section, Course.all, :id, :name) %>
  </div>

这给出了 "Courses must exist"

的错误

之前我有:

  <div class="field">
  <%= form.label "Courses", class: 'courses'%>
  <%= form.collection_select(:course_ids, Course.all, :id, :name) %>

这没有给出错误并允许我创建一个部分,只是没有将 selected 课程添加到部分数据库。

https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select

从阅读看来:名称应该在课程的模型部分定义,但是当我尝试时它给出了一个错误。我还意识到我没有将它设置为将课程记录到特定的部分 ID,这就是为什么在创建新部分时它不保存它的原因。我的问题是,我要添加或修改什么才能使其正常工作?使用集合 select 是错误的做法吗?

编辑以包含 sections_controller.rb

class SectionsController < ApplicationController
  before_action :set_section, only: [:show, :edit, :update, :destroy]

  # GET /sections
  # GET /sections.json
  def index
    @sections = Section.all
  end

  # GET /sections/1
  # GET /sections/1.json
  def show
  end

  # GET /sections/new
  def new
    @section = Section.new
  end

  # GET /sections/1/edit
  def edit
  end

  # POST /sections
  # POST /sections.json
  def create
    @section = Section.new(section_params)

    respond_to do |format|
      if @section.save
        format.html { redirect_to @section, notice: 'Section was successfully created.' }
        format.json { render :show, status: :created, location: @section }
      else
        format.html { render :new }
        format.json { render json: @section.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /sections/1
  # PATCH/PUT /sections/1.json
  def update
    respond_to do |format|
      if @section.update(section_params)
        format.html { redirect_to @section, notice: 'Section was successfully updated.' }
        format.json { render :show, status: :ok, location: @section }
      else
        format.html { render :edit }
        format.json { render json: @section.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /sections/1
  # DELETE /sections/1.json
  def destroy
    @section.destroy
    respond_to do |format|
      format.html { redirect_to sections_url, notice: 'Section was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_section
      @section = Section.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def section_params
      params.require(:section).permit(:semester, :number, :course, :room_number)
    end
end

我想我需要以某种方式将它们与最后一部分联系起来:

 def section_params
          params.require(:section).permit(:semester, :number, :course, :room_number)

编辑:
(来源:rubyisonrails.com
http://rubyisonrails.com/pictures/part2.PNG">

首先,您应该将 Section 模型中的 courses 更改为 coursebelongs_to 的关联名称应始终为 singular

class Section < ApplicationRecord
  belongs_to :course #singular name
end

其次,您应该有 course_id 列,而不是 table 部分。您可以生成将在 table

中反映这些更改的迁移
rails g migration modify_sections

上面的命令应该会在 db/migrate 文件夹下生成一个类似 xxxxxxxmodify_sections.rb 的文件。打开文件并添加

def change
  add_column :sections, :course_id, :integer
  remove_column :sections, :course, :integer
end

然后rake db:migrate

现在将 collection_select 更改为如下所示

<%= form.collection_select(:course_id, Course.all, :id, :name) %>

并在 sections_controller#create 中添加

@section.course_id = params[:section][:course_id]

respond_to do |format|

之前

最后,在section_params方法中将course改为course_id

def section_params
  params.require(:section).permit(:semester, :number, :course_id, :room_number)
end

注:

由于你对这项技术很陌生,建议你跟着Guides学习。