我是 Rails 新手,在我的数据库中指定几个实体和关系时遇到了一些问题。
让我们假设以下实体。
赛车实体
迁移文件如下所示:
class CreateRacers < ActiveRecord::Migration
    def self.up
        create_table :racers, options: "ENGINE=InnoDB" do |t|
        t.string :email, limit: 60, null: false
        end
        add_index :racers, :email, unique: true
        execute "ALTER TABLE racers MODIFY id INT UNSIGNED AUTO_INCREMENT;"
    end
    def self.down
        drop_table :racers
    end
end
模型文件如下所示:
class Racer < ActiveRecord::Base
    attr_accessible :email
    validates_uniqueness_of :email
    before_save { |racer| racer.email = email.downcase }
    # Email validation
    VALID_EMAIL_REGEX = /([\w+.]+)@[a-z\d\-.]+\.[a-z]+\z/i
    validates :email, presence: true, length: {maximum: 60}, format: { with: VALID_EMAIL_REGEX }
    has_many :tracks, dependent: :delete_all
end
追踪实体
迁移文件如下所示:
class CreateTracks < ActiveRecord::Migration
    def self.up
        create_table :tracks, options: "ENGINE=InnoDB" do |t|
            t.column :user_id, 'integer unsigned', null: false
            t.string :description, limit: 250, null: false
            t.string :image, null: true
        end
        execute "ALTER TABLE tracks MODIFY id INT UNSIGNED AUTO_INCREMENT;"
        add_foreign_key :tracks, :racers
    end
    def self.down
        remove_foreign_key :tracks, :racers
        drop_table :tracks
    end
end
模型文件如下所示:
class Track < ActiveRecord::Base
    attr_accessible :description, :image
    validates :description, presence: true, length: {maximum: 250}
    belongs_to :racer
    validates_presence_of :racer_id
    has_many :stops, dependent: :delete_all
end
停止实体
迁移文件如下所示:
class CreateStops < ActiveRecord::Migration
    def self.up
        create_table :stops, options: "ENGINE=InnoDB" do |t|
            t.column :track_id, 'integer unsigned', null: false
            t.column :coordinates, :point, null: false
            t.string :name, limit: 30, null: true
            t.column :sequence_order, 'integer unsigned', null: false
        end
        execute "ALTER TABLE stops MODIFY id INT UNSIGNED AUTO_INCREMENT;"
        add_foreign_key :stops, :tracks
    end
    def self.down
        remove_foreign_key :stops, :tracks
        drop_table :stops
    end
end
模型文件如下所示:
class Stop < ActiveRecord::Base
    attr_accessible :coordinates, :name, :sequence_order
    validates :name, presence: true, length: {maximum: 30}
    validates :coordinates, presence: true
    validates :spot_sequence_order, presence: true
    belongs_to :track
    validates_presence_of :track_id
    has_one :challenge, dependent: :delete_all
end
Challenge、Puzzle、Quiz、QuizOption 实体(问题出在哪里)
已在Stop实体has_one挑战上方看到,我希望该挑战除其他外是Quiz或Puzzle。挑战 belongs_to a Stop。_ 到目前为止,我有以下迁移:
class CreatePuzzles < ActiveRecord::Migration
    def self.up
        create_table :puzzles, options: "ENGINE=InnoDB" do |t|
            t.string :image_path, null: false
            t.int :ver_split, null: false, default: 4
            t.int :hor_split, null: false, default: 4
        end
        execute "ALTER TABLE puzzlies MODIFY id INT UNSIGNED AUTO_INCREMENT;"
    end
    def self.down
        drop_table :quizzes
    end
end
class CreateQuizzes < ActiveRecord::Migration
    def self.up
        create_table :quizzes, options: "ENGINE=InnoDB" do |t|
            t.string :question, null: false
        end
        execute "ALTER TABLE quizzes MODIFY id INT UNSIGNED AUTO_INCREMENT;"
    end
    def self.down
        drop_table :quizzes
    end
end
以及以下型号
class Puzzle < ActiveRecord::Base
    attr_accessor :image_path, :ver_split, hor_split
    validates :image_path, presence: true, allow_blank: false
    validates :ver_split, allow_blank: false
    validates :hor_split, allow_blank: false
    belongs_to :stop
end
class Quiz < ActiveRecord::Base
    attr_accessor :question
    validates :question, presence: true, length: { maximum: 255 }, allow_blank: false
    belongs_to :spot
    has_many :quiz_options
end
测验有几个答案,其中一个或多个是正确的。
class CreateQuizOptions < ActiveRecord::Migration
    def self.up
        create_table :quiz_options do |t|
            t.column :quiz_id, 'integer unsigned', null: false
            t.string :option, null: false
            t.boolean :is_correct, null: false, default: false
        end
        add_foreign_key :quiz_options, :quizzes
        execute "ALTER TABLE quiz_options MODIFY id INT UNSIGNED AUTO_INCREMENT;"
    end
    def self.down
        remove_foreign_key :quiz_options, :quizzes
        drop_table :quiz_options
    end
end
class QuizOption < ActiveRecord::Base
    attr_accessor :option, :is_correct
    validates :option, presence: true, length: { maximum: 255 }
    validates_inclusion_of :is_correct, in: [true,false]
    belongs_to :quiz
    validates_presence_of :quiz_id
end
问题
我应该如何指定我的迁移、模型和控制器来实现这个目标?
我找到了几个 STI 和多态关联的例子,但我不知道要应用哪个以及如何将它们应用于这种情况。
首先,我尝试使用 STI 并在Challenge表中声明所有必要的字段,然后Quiz and Puzzle模型继承自Challenge模型。问题是我不知道把has_many :quiz_options放在哪里。
然后我尝试使用此处和此处解释的多态关联,但老实说,我无法理解如何使其适应这种特定情况。
提前致谢。
编辑:我忘了说我正在使用 MySQL。我也有一些宝石来管理空间数据类型(rgeo、activerecord-mysql2spatial-adapter)和foreign_keys(foreigner)。