0

私はレールに慣れていないので、データベースでいくつかのエンティティと関係を指定するのに問題があります。

次のエンティティを想定しましょう。

レーサーエンティティ

移行ファイルは次のようになります。

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 challenge を見てきましたが、そのChallengeQuizまたはPuzzleにしたいと考えています。ChallengeStopに属します。これまでのところ、次の移行があります。

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

クイズにはいくつかの答えがあり、1 つ以上が正解です。

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 と Polymorphic-Associations の例をいくつか見つけましたが、どれを適用すればよいのか、このケースにどのように適用するのかわかりません。

最初に、STI を使用してChallengeテーブルで必要なすべてのフィールドを宣言しようとしました。次に、 QuizおよびPuzzleモデルがChallengeモデルから継承されます。問題は、 has_many :quiz_optionsをどこに置くべきかわからないことです。

次に、ここここで説明されているポリモーフィック アソシエーションを使用しようとしましたが、この特定のケースにそれを適応させる方法を正直に理解できません。

前もって感謝します。

編集:MySQLを使用していることを忘れていました。また、空間データ型 (rgeo、activerecord-mysql2spatial-adapter) およびforeign_keys (foreigner) を管理するための gem もいくつかあります。

4

1 に答える 1

0

わかりました、単一テーブルの継承を適用​​することで、私自身の問題を解決したと思います。

結果はきれいではありませんが、うまくいきます。他のソリューションに関する適切な情報が不足しているため、今のところそれに固執します.

それでは、私の例に戻りましょう。

RacerTrackStopエンティティはそのままで、変更はありません。

チャレンジの移行は次のようになります。

class CreateChallenges < ActiveRecord::Migration
    def self.up
        create_table :challenges, options: "ENGINE=InnoDB" do |t|
            t.column :stop_id, 'integer unsigned', null: false
            t.string :type
            # Common attributes to all challenges
            t.string :description, null: false
            # Puzzle attributes
            t.string :image_path
            t.int :vert_split
            t.int :hor_split
            # Quiz attributes
            t.string :question
        end
        add_foreign_key :challenges, :stops
        execute "ALTER TABLE quizzes MODIFY id INT UNSIGNED AUTO_INCREMENT;"
    end

    def self.down
        remove_foreign_key :challenges, :stops
        drop_table :quizzes
    end
end

このテーブルでは、QuizzesPuzzlesの両方を指定するために必要なすべてのフィールドを追加しました。

モデルは次のようになります。

class Challenge < ActiveRecord::Base
    validates_presence_of :spot_id, :description

    attr_accessible :description, :image_path

    # Validate description attribute
    validates :description, length: { maximum: 255 }, allow_blank: false
    # Validates image type
    VALID_IMAGE_TYPE_REGEX = /^[\/]?([\w]+[\/])*([\w]+\.(png|jpg))$/
    validates :image_path, length: { maximum: 255 }, allow_blank: true, format: { with: VALID_IMAGE_TYPE_REGEX }

    # Validates type attribute
    validates_inclusion_of :type, in: %w( Quiz Puzzle )

    # Associations
    belongs_to :stop
    has_many :quiz_options
end
class Puzzle < Challenge
    validates_presence_of :image_path
    attr_accessor :image_path, :ver_split, hor_split

    validates :image_path, allow_blank: false
    validates :ver_split, allow_blank: false
    validates :hor_split, allow_blank: false
end
class Quiz < Challenge
    validates_presence_of :question
    attr_accessor :question

    validates :question, length: { maximum: 255 }, allow_blank: false
end

すべてを終了すると、QuizOptionの移行とモデルは次のようになります。

class CreateQuizOptions < ActiveRecord::Migration
    def self.up
        create_table :quiz_options do |t|
            t.column :challenge_id, 'integer unsigned', null: false
            t.string :option, null: false
            t.boolean :is_correct, null: false, default: false
        end
        add_foreign_key :quiz_options, :challenges
        execute "ALTER TABLE quiz_options MODIFY id INT UNSIGNED AUTO_INCREMENT;"
    end

    def self.down
        remove_foreign_key :quiz_options, :challenges
        drop_table :quiz_options
    end
end
class QuizOption < ActiveRecord::Base
    validates_presence_of :challenge_id, :option
    attr_accessor :option, :is_correct

    validates :option, length: { maximum: 255 }
    validates_inclusion_of :is_correct, in: [true,false]

    belongs_to :challenge
end

このようにして、すべてが思い通りに機能します。

于 2012-11-02T01:01:32.457 に答える