我使用的是:rails 6.1.4ruby 3.1.1p18

我上一次在Rails中使用多对多关联已经有一分钟了,这一次我有点迷茫.如有任何帮助/建议,我们将不胜感激.

如果需要,我很乐意编辑帖子以添加更多信息.

我在我的Rails应用程序living_muay_thai/中创建了一个目录,并在其中try 在两个模型之间创建many to many关系.我把所有的代码都准备好了.使用console (development),我try 在JOINS表中创建一条记录,但得到一个错误:

3.1.1 :009 > sb.errors.full_messages
 => ["Living muay thai student must exist", "Living muay thai badge must exist"]

我的代码是:

generate models/migrations:

rails generate model living_muay_thai/Student
rails generate model living_muay_thai/Badge

此时,我不记得我是如何创建JOINS表的.我想我try 了几个不同的生成行,但都以索引名的错误太长而结束,所以我最终手动编辑它,以使错误变得令人满意.

Migrations:

Students:

class CreateLivingMuayThaiStudents < ActiveRecord::Migration[6.1]
  def change
    create_table :living_muay_thai_students do |t|
      t.string :fname 
      t.string :lname 
      t.timestamps
    end
  end
end

--------------------------
Badges:

class CreateLivingMuayThaiBadges < ActiveRecord::Migration[6.1]
  def up
    create_table :living_muay_thai_badges do |t|
      t.string  :color 
      t.string  :category
      t.integer :number

      t.timestamps
    end
  end

  def down
    drop_table :living_muay_thai_badges
  end
end

------------------
StudentBadges (joins table)

class CreateLivingMuayThaiStudentBadges < ActiveRecord::Migration[6.1]
  def change
    create_table :living_muay_thai_student_badges do |t|
      t.integer :student_id
      t.integer :badge_id

      t.timestamps
    end
    add_index :living_muay_thai_student_badges, :student_id, name: 'students_index'
    add_index :living_muay_thai_student_badges, :badge_id, name: 'badges_index'
  end
end

对于学生证迁移,我是这样做的(上图),因为按照几个教程提到的方式做会出错……Index name too long...左右,这种方式奏效了.

Models:

Students:

# == Schema Information
#
# Table name: living_muay_thai_students
#
#  id         :bigint           not null, primary key
#  fname      :string
#  lname      :string
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
class LivingMuayThai::Student < ApplicationRecord
    has_many :living_muay_thai_student_badges
    has_many :living_muay_thai_badges, through: :living_muay_thai_student_badges

    has_many :living_muay_thai_levels
end

----------------------
Badges:

# == Schema Information
#
# Table name: living_muay_thai_badges
#
#  id         :bigint           not null, primary key
#  category   :string
#  color      :string
#  number     :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
class LivingMuayThai::Badge < ApplicationRecord
    has_many :living_muay_thai_student_badges
    has_many :living_muay_thai_students, through: :living_muay_thai_student_badges
end

---------------------
StudentBadge

# == Schema Information
#
# Table name: living_muay_thai_student_badges
#
#  id         :bigint           not null, primary key
#  badge_id   :integer
#  student_id :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#
# Indexes
#
#  badges_index    (badge_id)
#  students_index  (student_id)
#
class LivingMuayThai::StudentBadge < ApplicationRecord
  belongs_to :living_muay_thai_student
  belongs_to :living_muay_thai_badge
end

我还没有充实控制器的内容.在此之前,我想在控制台中测试一下.我不确定这和我的问题有什么因果关系.(??)

控制台:

# create a student:
3.1.1 :001 > s1=LivingMuayThai::Student.create(:fname => 'John', :lname=>'Smith')
# works

# create a badge:
3.1.1 :002 > b1=LivingMuayThai::Badge.create(:color => 'White', :category => 'Beginner', :number => 1)
# works

# create record in joins table:
3.1.1 :003 > sb=LivingMuayThai::StudentBadge.create(:student_id => s1.id, :badge_id => b1.id)
 => #<LivingMuayThai::StudentBadge:0x00007f713867a970 id: nil, student_id: 11, badge_id: 140, created_at: nil, updated_at: nil> 
3.1.1 :004 > sb.valid?
 => false 
3.1.1 :005 > sb.errors.full_messages
 => ["Living muay thai student must exist", "Living muay thai badge must exist"]

再次感谢您的关注.非常感谢.

推荐答案

问题是您如何定义您的关联,以及您拥有哪些列和表名.现在,它们并不符合Rails约定

使用JOIN TABLE的显式列名定义belongs_to:

class LivingMuayThai::StudentBadge < ApplicationRecord
  belongs_to :living_muay_thai_student, class_name: 'LivingMuayThai::Student', foreign_key: :student_id
  belongs_to :living_muay_thai_badge, class_name: 'LivingMuayThai::Badge', foreign_key: :badge_id
end

您还可以重命名列名.在这种情况下,您不需要指定:foreign_key个选项

change_table :living_muay_thai_student_badges do |t|
  t.rename :student_id, :living_muay_thai_student_id
  t.rename :badge_id, :living_muay_thai_badge_id
end

第二种 Select 是根据列名更改关联名称(并保持列名不变(Student_id和badge_id):

class LivingMuayThai::StudentBadge < ApplicationRecord
  belongs_to :student
  belongs_to :badge
end

Ruby-on-rails相关问答推荐

Rails 7涡轮框架和多种形式与形式值有关

Rails HotWire和View Components:涡轮框架不会取代内容

错误正在被ViewComponent、Ruby on Rails中吞噬

ActiveAdmin:的呈现索引表在父级的显示页中有许多资源

如何从 gem 覆盖 JSONAPI.configure

nginx 中的 Rails 7 Active Storage - 图像中途停止加载 net::ERR_HTTP2_PROTOCOL_ERROR 200

为什么 2 个关键字参数被解释为 1?

如何通过graphqlMutations 从rails销毁当前用户会话

BigDecimals 的总和最终成为整数 [Ruby on Rails]

如何在 Rails 中注释掉 ERB?

你如何发布到 Capybara 中的 URL?

使用brew 软件安装了 elasticsearch,但找不到配置文件

在 Rails 3.2 中更新多行

为 ActionMailer 渲染不同的视图(模板)

在 Rails 中,如何处理多个选中的复选框,只需拆分 , 或?

Rails(或 Ruby):Yes/No 而不是 True/False

将根 url 重定向到 Rails 应用程序中的其他位置

奇怪的406 不可接受错误

在 factory_girl 中填充与 children 的关联

我如何在具有活动记录的 Rails 中使用两个不同的数据库?