Помощники Devise для наследования одной таблицы Rails

Я создал модель User с помощью Devise и добавил столбец type и т. д., чтобы модели Student и Teacher могли наследовать от него. Все это прекрасно работало. Моя модель Teacher имеет отношение один ко многим к модели Course, где хранятся все данные о курсах учителей.

Моя проблема: помощник Devise current_user.courses не работает, потому что в таблице courses нет столбца user_id. Как сделать так, чтобы current_user мог разрешать .courses, даже если атрибут в курсах называется teacher_id?

Я новичок в Rails, поэтому буду признателен за любую помощь! :)

РЕДАКТИРОВАТЬ: уточненный вопрос и добавленная схема и модели.

# schema.rb:
create_table "courses", force: :cascade do |t|
    t.string   "title"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer  "teacher_id"
    t.index ["teacher_id"], name: "index_courses_on_teacher_id"
  end

  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.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
    t.string   "name"
    t.string   "type"
    t.integer  "quiz_session_id"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["quiz_session_id"], name: "index_users_on_quiz_session_id"
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

# /app/models/course.rb:
class Course < ApplicationRecord
  belongs_to :teacher
  has_many :students

  delegate :teachers, :students, to: :users
end

# /app/models/user.rb:
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :courses

  # Which users subclass the User model
  def self.types
    %w(Teacher Student)
  end

  # Add scopes to the parent models for each child model
  scope :teachers, -> { where(type: 'Teacher') }
  scope :students, -> { where(type: 'Student') }

end

# /app/models/teacher.rb:
class Teacher < User
end

person megahra    schedule 13.05.2017    source источник
comment
Можете ли вы добавить свои schema.rb и/или модели?   -  person Sebastian Palma    schedule 13.05.2017


Ответы (3)


Вы можете определить своих собственных помощников следующим образом:

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception
  helper_method :current_teacher, :current_student, 
                :teacher_logged_in?, :student_logged_in?

  private

    def current_teacher
      @current_teacher ||= current_user if user_signed_in? and current_user.class.name == "Teacher"
    end

    def current_student
      @current_student ||= current_user if user_signed_in? and current_user.class.name == "Student"
    end

    def teacher_logged_in?
      @teacher_logged_in ||= user_signed_in? and current_teacher
    end

    def student_logged_in?
      @student_logged_in ||= user_signed_in? and current_student
    end
end

Я не выполнял эти синтаксисы, но я писал что-то подобное в прошлом, поэтому, если вы столкнулись с какой-либо синтаксической ошибкой, напишите об этом в комментарии.

РЕДАКТИРОВАТЬ:

Увидев обновленный код модели, я думаю, что изменение ассоциации course в пользовательской модели, как показано ниже, будет работать для вас:

has_many :courses, :foreign_key  => "teacher_id"
person Sajan    schedule 13.05.2017
comment
Спасибо, это фактически позволяет мне вызывать current_teacher.courses, но выдает ту же ошибку, что и раньше: SQLite3::SQLException: no such column: courses.user_id: SELECT "courses".* FROM "courses" WHERE "courses"."user_id" = ?. Я бы предпочел решение, в котором current_user.courses работает как для Teacher, так и для Student! - person megahra; 13.05.2017
comment
Еще один вопрос: я хотел бы, чтобы current_user.courses работало независимо от того, вошел ли я в систему как ученик или как учитель. Сейчас это должно работать только для модели Учителя, поскольку я добавил только => "teacher_id", как мне изменить ее, чтобы она работала и для "student_id"? @саджан - person megahra; 13.05.2017
comment
О, извините, дополнительная информация: Студент - курс - это отношение многие ко многим, выраженное таблицей с именем "courses_students", содержащей соответствующие course_id и student_id каждой записи. - person megahra; 13.05.2017
comment
Я полагаю, у вас есть has_many :courses в Student классе. это не работает? любая ошибка? Вы пытались добавить ту же foreign_key опцию student_id в эту ассоциацию? - person Sajan; 13.05.2017
comment
Нет, модель Student наследует отношение has_many :courses от модели User. В модели Student не определены дополнительные отношения. Если я добавлю строки has_many :courses, :foreign_key => "teacher_id" и has_many :courses, :foreign_key => "student_id" в модель User, будет работать только вторая строка. - person megahra; 13.05.2017
comment
Мой вопрос: при вызове current_user.courses для пользователя типа Студент, как модель узнает, что ей нужно искать в таблице courses_students, чтобы выбрать все курсы для текущего пользователя? - person megahra; 13.05.2017
comment
вы знаете? @саджан - person megahra; 14.05.2017
comment
Конечно, вы не можете использовать одну и ту же ассоциацию дважды только с другим внешним ключом. И поскольку вы сохраняете запись ассоциации в другой таблице, и это отношение «многие ко многим», я думаю, вам следует использовать ассоциацию has_and_belongs_to_many. проверьте руководство по рельсам для этой ассоциации. - person Sajan; 14.05.2017

Бегать:

rails generate migration AddUserReferenceToCourses user:references

Я думаю, что это создаст миграцию, которая добавит user_id к курсам.

person code4fun    schedule 13.05.2017
comment
О, я не совсем ясно выразился, извините: отношения между учителем и курсами созданы намеренно, поскольку другой класс, наследуемый от пользователя (модель «студент»), имеет другое отношение к курсам. - person megahra; 13.05.2017

Вы можете добавить миграцию в таблицу курсов:

rails g migration add_user_id_to_courses user:references

Это добавит belongs_to :user в файл course.rb. Затем перейдите в файл user.rb и добавьте:

has_many :courses

Это отношение позволит вам вызывать пользователя из курса или курса из пользователя.

person hashrocket    schedule 13.05.2017