【问题标题】:ActiveRecord + postgresql + data constraintsActiveRecord + postgresql + 数据约束
【发布时间】:2011-01-24 19:39:54
【问题描述】:

我想在我的 Rails 应用程序中使用 ActiveRecord,但我想在 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 中的数据库迁移文件中?

感谢您给我的任何帮助。

【问题讨论】:

  • +1:对数据的约束应该始终在数据库中,然后自动添加到 ActiveRecord 模型中。 Rails 和 ActiveRecord 只是访问我们数据的一种方式,而不是唯一的强制检查点。这确保了完整性并尊重 DRY 原则。因此,您的问题很有趣,任何好的答案也会很有趣。

标签: ruby-on-rails-3 postgresql database-design activerecord


【解决方案1】:

上述CREATE TABLE 语句唯一的错误是USER 是保留字,必须加引号。因此,

CREATE TABLE "User" ( ... );

会起作用。 (选择您想要的名称的大小写。)

【讨论】:

  • 谢谢。我做了更正。您是否知道如何从违反约束中获取自定义错误消息?
  • 您可以在客户端或存储过程中捕获特定的 SQLSTATE 错误代码。但是没有办法直接在数据库系统中修改错误信息。
【解决方案2】:

事实上你应该有表Users,否则你可能会遇到更多问题。 当然你可以定义其他的屈折变化,但它完全是错误的,而不是 railsway。

class User
  ...
end

那么 创建表 Users ...

【讨论】:

    【解决方案3】:

    这是一个使用 Oracle(不是 Postgresql)的例子,但想法是一样的。只有目录不同。请注意,我为非空约束命名了我的约束“table_column_nn”。下面的解决方案可能会得到改进。

    假设代表作者的模型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.
    

    【讨论】:

      猜你喜欢
      • 2017-01-18
      • 2011-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 2020-04-19
      • 1970-01-01
      相关资源
      最近更新 更多