【问题标题】:Rails 5 - Creating two new Models Inheriting from a base ModelRails 5 - 创建两个从基础模型继承的新模型
【发布时间】:2017-12-01 22:43:34
【问题描述】:

假设我有一个User 模型及其属性(名字、姓氏等),我想创建两个新模型TeacherStudent

它们将继承User 模型属性,并且它们将具有特定属性。例如,Student 模型将具有 file 属性,Teacher 模型将具有 subject 属性。

我正在阅读有关 STI(单表继承)和多态关系的文章。

我应该寻找什么来实现这一点?你有什么例子可以展示吗?

【问题讨论】:

标签: ruby-on-rails inheritance


【解决方案1】:

如果您在users 表上创建一个名为“type”的属性,Rails 将自动假定您要实现 STI。然后,创建教师和学生模型就像扩展 User 类一样简单。子类的名称将自动插入到类型列中,并按照您的预期用于过滤查询。

user.rb

class User < ApplicationRecord
end

teacher.rb

class Teacher < User
end

student.rb

class Student < User
end

使用 STI,您可以将任一模型将使用的所有列放在同一个表中,并简单地忽略(默认为 null)在任何给定情况下不适用的列。

多态关系允许两个或多个表填充相同的关联。如果您想使用三个不同的表,但要确保用户具有教师学生,则可以将其建模为多态 belongs_to。缺点是您需要返回用户模型才能访问共享信息,即teacher.user.first_name

【讨论】:

  • 我不喜欢在Users 表中包含具有空值的列的想法......也许我会采用多态方式。谢谢!
【解决方案2】:

我发现这颗宝石看起来像我正在寻找的东西。我用它玩了一点,它确实对我有用。

https://github.com/krautcomputing/active_record-acts_as

所以,就我而言,我已将其添加到 Gemfile:

gem 'active_record-acts_as'

然后:

$ bundle

这些是我的迁移:

# 20171202142824_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.string :first_name
      t.string :last_name
      t.date :birth_date
      t.string :dni
      t.string :cuil
      t.string :email
      t.string :phone
      t.string :address
      t.string :postal_code
      t.string :city
      t.string :state
      t.string :country
      t.actable # This is important!
      t.timestamps
    end
  end
end

# 20171202142833_create_students.rb
class CreateStudents < ActiveRecord::Migration[5.1]
  def change
    create_table :students do |t|
      t.string :file
      # Look, there is no timestamp.
      # The gem ask for it to be removed as it uses the User's timestamp
    end
  end
end

# 20171202142842_create_teachers.rb
class CreateTeachers < ActiveRecord::Migration[5.1]
  def change
    create_table :teachers do |t|
      # Look, there is no timestamp.
      # The gem ask for it to be removed as it uses the User's timestamp
    end
  end
end

这些是我的模型:

# user.rb
class User < ApplicationRecord
  actable
  validates_presence_of :first_name, :last_name

  def full_name
    [last_name.upcase, first_name].join(', ')
  end
end

# student.rb
class Student < ApplicationRecord
  acts_as :user
  validates_presence_of :file
end

# teacher.rb
class Teacher < ApplicationRecord
  acts_as :user
end

现在,通过所有这些设置,您可以简单地创建一个新学生和一个新教师:

Student.create!(first_name: 'John', last_name: 'Doe', file: 'A125')
=> #<Student id: 3, file: "A125">


Teacher.create!(first_name: 'Max', last_name: 'Power')
=> #<Teacher id: 1>

您可以访问用户的所有方法和属性。例如:

Teacher.last.full_name
=> "POWER, Max"

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
  • 完成!添加了代码示例。谢谢!
猜你喜欢
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-24
相关资源
最近更新 更多