ActiveRecord + postgresql + ограничения данных - PullRequest
4 голосов
/ 24 января 2011

Я хотел бы использовать ActiveRecord в своем приложении Rails, но я бы хотел кодировать ограничения данных в базе данных PostgreSQL, а не в моделях ActiveRecord.

Например, если у меня есть модель, сгенерированная скаффолдом,

 rails generate scaffold User name:string email:string yearofbirth:integer

Я хочу убедиться, что имя достаточно длинное.например,

 class User < ActiveRecord::Base
   validates :name, :length => { :maximum => 140 }
   validates_uniqueness_of :name
   validates_numericality_of :yearofbirth, :greater_than_or_equal_to => 1900
 end

Эти проверки хороши тем, что ActiveRecord выдает на экран несколько хороших сообщений об ошибках, если кто-то пытается добавить неверные данные.

Однако я хотел бы закодировать правила в самой базе данных и заставить базу данных выдавать такие же красивые и информативные сообщения об ошибках в ActiveRecord, которые затем передают их на уровень представления.Например,

 create table "Users" (
   id integer unique, 
   name varchar(140) unique check(length(name)<140), 
   email varchar(255),
   yearofbirth integer check (yearofbirth >= 1900) 
 );

Что мне нужно сделать в PostgreSQL или ActiveRecord, чтобы это произошло?Когда я попробовал его с помощью инструмента pgAdmin III, он выдавал сообщения об ошибках, но я бы хотел их настроить.

Кроме того, есть ли способ кодировать эти правила базы данных прямо в файлы миграции базы данных в Ruby?

Я ценю любую помощь, которую вы можете мне оказать.

Ответы [ 3 ]

1 голос
/ 25 января 2011

На самом деле у вас должна быть таблица Users , в противном случае вы можете получить гораздо больше проблем.Конечно, вы можете определить другие перегибы, но это просто неправильно и не рельсово.

class User
  ...
end

, затем создайте таблицу Users ...

1 голос
/ 15 декабря 2011

Вот пример использования Oracle (не Postgresql), но идея та же. Только каталог отличается. Обратите внимание, что я назвал свое ограничение "table_column_nn" для ограничения, не равного NULL. Решение ниже может быть улучшено.

Скажем, модель Author, представляющая автора, не должна иметь имя NULL.

class Author < ActiveRecord::Base
  has_and_belongs_to_many :books

  r = ActiveRecord::Base.connection.select_one("select CONSTRAINT_NAME from user_constraints where TABLE_NAME = 'AUTHORS' and constraint_name like '%_NN'")
  m = r["constraint_name"].match(/^[^_]*_([^_]*)_NN$/)
  if !m.nil?
    column = m[1]
    validates column.downcase.to_sym, :presence => true
  end
end

SQL-скрипт для настройки схемы:

create table authors (
    id integer primary key,
    name varchar2(100) constraint authors_name_nn not null,
    updated_at timestamp with local time zone,
    created_at timestamp with local time zone
);

Запрос SQL на БД дает следующее:

select constraint_name, search_condition from user_constraints where table_name = 'AUTHORS' and constraint_name like '%_NN';
CONSTRAINT_NAME     SEARCH_CONDITION
---------------     ----------------------
AUTHORS_NAME_NN      "NOM" IS NOT NULL

1 row selected.
1 голос
/ 24 января 2011

Единственное, что не так с приведенным выше утверждением CREATE TABLE, это то, что USER является зарезервированным словом и должно быть заключено в кавычки.Следовательно,

CREATE TABLE "User" ( ... );

будет работать.(Выберите нужную заглавную букву.)

...