Rails 5 - 创建两个新模型继承基础模型

时间:2017-12-01 22:43:34

标签: ruby-on-rails inheritance

假设我有User模型及其属性(first_name,last_name等),我想创建两个新模型TeacherStudent

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

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

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:-1)

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

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"