简体   繁体   中英

Rails: Undefined method error with additional ActiveRecord association

I am new to rails learning coding for fun. My goal is to let a teacher see list all posts made users who have that teacher. Posts belong to users, and users belong to teachers.

Models:

class User < ActiveRecord::Base
belongs_to :teacher
has_many :posts, dependent: :destroy

class Teacher < ActiveRecord::Base
has_many :user_posts, through: :users, source: :posts

class Post < ActiveRecord::Base
  belongs_to :user

The teachers controller:

class TeachersController < ApplicationController
  before_action :find_teacher, only: [:index]

def index
 @posts = @teacher.user_posts
end

private
  def find_teacher
    @teacher = current_user
  end 
end

I am struggling with @posts. I keep getting errors for undefined method for `user_posts'. I am wondering what I have done wrong and where to define it.

Schema.rb (just relevant parts)

create_table "teachers", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.inet     "current_sign_in_ip"
    t.inet     "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
  end

  add_index "teachers", ["email"], name: "index_teachers_on_email", unique: true, using: :btree
  add_index "teachers", ["reset_password_token"], name: "index_teachers_on_reset_password_token", unique: true, using: :btree

  create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.inet     "current_sign_in_ip"
    t.inet     "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
    t.string   "username"
    t.string   "TeacherEmail"
    t.string   "teacher"
  end

I tried figuring this out all day yesterday and this morning and am truly stuck. Thanks in advance for your time.

Firstly, if User belongs_to :teacher , the schema of table Users should have column teacher_id with integer type.

t.integer "teacher_id"

Then if Teacher manager many users, you have to define it in Teacher model. Then you can create a method to query for all posts made by users who have that teacher:

class Teacher < ActiveRecord::Base
  has_many :users

  def user_posts
    Post.where(id: users.map(&:id))
  end
end

You are missing user model association in teacher model.

class User < ActiveRecord::Base
  belongs_to :teacher
  has_many :posts, dependent: :destroy
end

class Teacher < ActiveRecord::Base
  has_many :users
  has_many :posts, through: :users
end

class Post < ActiveRecord::Base
  belongs_to :user
end

Two things that strike me:

  • that there's no teacher_id foreign key on the users table. You need it for belongs_to .
  • it should be has_many in Teacher not belongs_to for the association with users.

Hint: after a migration, restart the server/console.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM