Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Many to Many Models Creating Records Via Console is not Working

I’m using: rails 6.1.4 and ruby 3.1.1p18

It’s been a minute since I’ve played with a many-to-many association in rails and I’m a bit lost on this one. Any help/tips will be greatly appreciated.

I’m happy to edit post to add more info if requested.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I’ve made a directory inside my rails app living_muay_thai/ and inside it I’m trying to create a many to many relationship between two models. I have all the code in place. Using the console (development), I try to create a record in the joins table I get an error:

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

My code:

generate models/migrations:

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

At this point I can’t remember how I created the joins table. I think I tried a few different generate lines but all ended up with errors on the index name too long, so I ended up editing it by hand to make that error happy.

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

For the student badges migration I did it this way (above) because doing the way a couple tutorials mentioned I was getting an error… Index name too long... So, this way worked.

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

I haven’t fleshed out the contollers yet. I wanted to test this in the console before I did that. I’m not sure it that has any causal relation to my problem. (??)

Console:

# 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"]

Thanks again for looking at this. Much appreciated.

>Solution :

The problem is how you define your associations and what columns and tables name you have. Now they are not corresponds to the Rails convention

Define belongs_to like this with explicit column names of join table

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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading