我刚刚开始在Rails 4中尝试使用本机Postgres数组类型,而且我遇到了一个我无法弄清楚的问题。如果数组属性的值不是数组,我希望应用程序引发错误。
之前,当我为该字段使用常规文本类型并使用Rails对其进行序列化时,我能够确保该属性是一个带有这样的自定义验证的数组:
def format_of_admin_email
regexp = /.+@.+\..+/i
if admin_emails.present? &&
(!admin_emails.is_a?(Array) || admin_emails.detect { |a| a.match(regexp).nil? })
errors[:base] << "admin_emails must be an array of valid email addresses"
end
end
但是现在该字段是Postgres数组,看起来Rails会自动将字符串输入转换为空数组,因此验证永远不会失败。这是我的迁移:
class AddAdminEmailsToLocations < ActiveRecord::Migration
def change
add_column :locations, :admin_emails, :text, array: true
end
end
如果我创建一个admin_emails是字符串的位置:
Location.create!(admin_emails: "this should fail")
它不会引发验证错误,并将admin_emails设置为空数组。
我做错了什么,或者这是Rails中的错误?
我还尝试检查输入是否是before_validation回调中的数组,并添加了puts admin_emails.present?
,但它返回false
,就像它从未看到过String输入一样。
答案 0 :(得分:0)
我认为您可以使用postgresql检查约束有效的电子邮件列格式。 或在您的应用程序中。 对于exp:
digoal=# create domain email as text constraint ck check (value ~ '^.+@.+\..+$');
CREATE DOMAIN
digoal=# select 'digoal'::email;
ERROR: value for domain email violates check constraint "ck"
digoal=# select 'digoal@1'::email;
ERROR: value for domain email violates check constraint "ck"
digoal=# select 'digoal@126.com'::email;
email
----------------
digoal@126.com
(1 row)
但它不能用于数组类型的电子邮件[]。
所以请使用check。
digoal=# create or replace function ck_email(i_email text[]) returns boolean as $$
declare
v text;
begin
foreach v in array i_email loop
if substring(v from '.+@.+\..+') is not null then
continue;
else
return false;
end if;
end loop;
return true;
end;
$$ language plpgsql strict;
CREATE FUNCTION
digoal=# create table t_email(id int, email text[] check (ck_email(email)));
CREATE TABLE
digoal=# insert into t_email values (1, array['digoal@126.com','a@e']::text[]);
ERROR: new row for relation "t_email" violates check constraint "t_email_email_check"
DETAIL: Failing row contains (1, {digoal@126.com,a@e}).
digoal=# insert into t_email values (1, array['digoal@126.com','a@e.com']::text[]);
INSERT 0 1
答案 1 :(得分:0)
所以在花了好几个小时试图弄清楚我做错了什么之后,我一直觉得这是Rails中的一个错误,我在Rails GitHub回购中打开了一个问题:https://github.com/rails/rails/issues/14716 < / p>
它没有被解雇,并且被标记了一些标签,这对我来说意味着Rails团队已经承认了这个错误。