【问题标题】:Setting up a has_many_through with separate database migrations rails 5使用单独的数据库迁移设置 has_many_through rails 5
【发布时间】:2019-01-29 18:11:10
【问题描述】:

所以我有以下功能,我有课程、课程模块和课程练习。

我有它,用户可以在完成所有模块后标记模块完成,课程设置为完成。

但是,这适用于所有用户,而不是单个用户。因此,例如,当前发生的情况是一个用户完成了课程,当它被标记为完成时,但如果我以第二个用户(尚未完成课程)的身份登录,它被标记为完成。

根据我的研究,我相信我可以使用has_many_through 关联来实现这一点,但我不确定如何设置它。

这是到目前为止我的设置方式。

schema.rb

create_table "course_exercises", force: :cascade do |t|
    t.string "title"
    t.text "description"
    t.string "video"
    t.integer "course_module_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "slug"
    t.index ["course_module_id"], name: "index_course_exercises_on_course_module_id"
    t.index ["slug"], name: "index_course_exercises_on_slug", unique: true
  end

  create_table "course_modules", force: :cascade do |t|
    t.string "title"
    t.integer "course_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "slug"
    t.boolean "complete", default: false, null: false
    t.index ["course_id"], name: "index_course_modules_on_course_id"
    t.index ["slug"], name: "index_course_modules_on_slug", unique: true
  end

  create_table "courses", force: :cascade do |t|
    t.string "title"
    t.text "summary"
    t.text "description"
    t.string "trailer"
    t.integer "price"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "slug"
    t.boolean "complete", default: false, null: false
    t.index ["slug"], name: "index_courses_on_slug", unique: true
  end

用户.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :trackable, :validatable

  has_one_attached :avatar

  has_many :courses

  def after_confirmation
    welcome_email
    super
  end

  protected

  def welcome_email
    UserMailer.welcome_email(self).deliver
  end
end

课程.rb

class Course < ApplicationRecord
  extend FriendlyId
  friendly_id :title, use: :slugged

  has_many :users
  has_many :course_modules

  validates :title, :summary, :description, :trailer, :price, presence: true

  def complete!
    update_attribute(:complete, true)
  end
end

course_module.rb

class CourseModule < ApplicationRecord
  extend FriendlyId
  friendly_id :title, use: :slugged

  belongs_to :course
  has_many :course_exercises

  validates :title, :course_id, presence: true

  scope :completed, -> { where(complete: true) }
  after_save :update_course, if: :complete?

  private

  def update_course
    course.complete! if course.course_modules.all?(&:complete?)
  end
end

已完成的模块

完成的课程

数据库:

课程

课程模块

但正如我上面提到的,它被分配给所有用户,而不是单个用户。

感谢您提供任何帮助。

【问题讨论】:

  • 一个选项可以是连接表user_course_modules 和附加列status。所以Userhas_many :course_modules, through: user_course_modules
  • @iGian 那么在 course_modules 表中创建一个新列,并使用用户 ID 索引该列?
  • 对我来说听起来不太好。我认为UserCourseModule 之间的连接表更好。然后,您可以将相同的逻辑应用于CourseExercise。无论如何,最好你自己尝试一些模拟。另外,请查看此文档:guides.rubyonrails.org/…
  • @iGian 所以一个新表,只是说迁移中的关联?这是我第一次这样做,所以我想确保我知道自己在做什么?
  • 只是一个新表(user_idcourse_module_idstatus 或其他)和几行关联代码。对于状态,您可以使用枚举。让我知道..

标签: ruby-on-rails ruby ruby-on-rails-5 associations has-many-through


【解决方案1】:

根据描述,您似乎需要另一张桌子 捕获用户明智的数据以显示已完成的模块。

但这里的另一个问题是您还需要记录进度 course_exersises 特定用户已完成,以便在完成后 您可以更新 course_module 的所有练习。

注意:下表中的输入仅在用户完成后才完成 给定练习,我们也将获得 rails 提供的时间戳。

用户

has_many :courses, through: :user_courses
has_many :exercises, through: :user_course_exercise

用户课程练习

belongs_to :user
belongs_to :course_exercise
#table columns
user_id
exercise_id

如果特定课程的所有练习都有 已完成。

用户课程

belongs_to :user
belongs_to :course_exercise
#table columns
user_id 
course_id

有两个表的方法是当你需要展示练习时 对应于特定用户的数据,那么您将使用 user_course_exercise 当需要完成的课程时,然后使用 user_course 表

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多