Вопрос

Мне нужно добавить новую целочисленную колонку в существующую таблицу в моем приложении Rails. В столбце могут быть только значения 1, 2, 3, поэтому я хотел бы добавить ограничение проверки в таблицу/столбца. Как мне указать это ограничение в миграции рельсов?

Это было полезно?

Решение

Миграция рельсов не обеспечивает никакого способа добавить ограничения, но вы все равно можете сделать это через миграцию, но передавая фактический SQL для выполнения ()

Создать файл миграции:

ruby script/generate Migration AddConstraint

Теперь в файле миграции:

class AddConstraint < ActiveRecord::Migration
  def self.up
    execute "ALTER TABLE table_name ADD CONSTRAINT check_constraint_name CHECK (check_column_name IN (1, 2, 3) )"
  end

  def self.down
    execute "ALTER TABLE table_name DROP CONSTRAINT check_constraint_name"
  end
end

Другие советы

Я только что опубликовал жемчужину для этого: Active_record-postgres-constrints. Анкет Как ПРОЧТИ МЕНЯ Там описывает, что вы можете использовать его с помощью файла db/schema.rb, и он добавляет поддержку следующих методов в миграции:

create_table TABLE_NAME do |t|
  # Add columns
  t.check_constraint conditions
  # conditions can be a String, Array or Hash
end

add_check_constraint TABLE_NAME, conditions
remove_check_constraint TABLE_NAME, CONSTRAINT_NAME

Обратите внимание, что в настоящее время поддерживается только Postgres.

Я только что работал, чтобы получить ограничение на проверку PostgreSQL для работы.

Решение Нилеша не совсем завершено; Файл db/schema.rb не будет включать ограничение, поэтому тесты и любые развертывания, которые используют DB: Setup, не получат ограничения. Согласно http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps

В то время как при миграции вы можете выполнить пользовательские операторы SQL, то, что схема не может восстановить эти операторы из базы данных. Если вы используете подобные функции, то вам следует установить формат схемы на: SQL.

Т.е. в наборе config/application.rb

config.active_record.schema_format = :sql

К сожалению, если вы используете PostgreSQL, вы можете получить ошибку при загрузке результирующего дампа, см. Обсуждение в Ошибка: должен быть владельцем языка plpgsql. Анкет Я не хотел идти по пути конфигурации PostgreSQL в этом обсуждении; Плюс в любом случае мне нравится иметь читаемый файл db/schema.rb. Так что это исключило пользовательский SQL в файле миграции для меня.

А https://github.com/vprokopchuk256/mv-core GEM, предложенный Valera, кажется многообещающим, но он поддерживает лишь ограниченный набор ограничений (и я получил ошибку, когда я попытался его использовать, хотя это может быть связано с несовместимостью с другими драгоценными камнями, которые я включаю).

Решение (взломать), с которым я пошел, состоит в том, чтобы вставить код модели вставить ограничение. Поскольку это все равно, как проверка, вот где я это выразил:

class MyModel < ActiveRecord::Base

    validates :my_constraint

    def my_constraint
        unless MyModel.connection.execute("SELECT * FROM information_schema.check_constraints WHERE constraint_name = 'my_constraint'").any?
            MyModel.connection.execute("ALTER TABLE my_models ADD CONSTRAINT my_constraint CHECK ( ...the SQL expression goes here ... )")
        end
    end

Конечно, это делает дополнительный выбор перед каждой проверкой; Если это проблема, решение будет заключаться в том, чтобы поместить его в патч с обезьяной «после подключения», например, обсуждается в Как запустить конкретный скрипт после подключения к Oracle с помощью Rails? (Вы не можете просто кэшировать результат выбора, потому что добавление проверки/ограничения происходит в рамках транзакции, которая может быть откат назад, поэтому вам нужно проверять каждый раз.)

Вы можете сделать это с GEM Migration Validators. См. Подробности здесь: https://github.com/vprokopchuk256/mv-core

С помощью этого драгоценного камня вы сможете определить проверку включения на уровне БД:

def change
  change_table :table_name do |t|
    t.integer :column_name, inclusion: [1, 2, 3]
  end
end

Более того, вы можете определить, как следует определить эту проверку, и даже сообщение об ошибке, которое должно быть показано:

def change
  change_table :posts do |t|
    t.integer :priority, 
              inclusion: { in: [1, 2, 3], 
                           as: :trigger, 
                           message: "can't be anything else than 1, 2, or 3" }
  end
end

Вы можете даже повысить уровень этой проверки от миграции на вашу модель:

class Post < ActiveRecord::Base 
  enforce_migration_validations
end

а затем валидация определяет в миграции также будет определяться как проверка ActiveModel в вашей модели:

Post.new(priority: 3).valid? 
=> true

Post.new(priority: 4).valid?
=> false

Post.new(priority: 4).errors.full_messages
=> ["Priority can't be anything else than 1, 2, or 3"]

Вы можете использовать Sequel жемчужина https://github.com/jeremyevans/eceerel

Sequel.migration do
  change do
    create_table(:artists) do
      primary_key :id
      String :name
      constraint(:name_min_length){char_length(name) > 2}
    end
  end
end
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top