Erlang-Web的Validation

我们都知道,作为一个与用户交互的系统,都存在找数据的交互。然后,由于用户输入的数据都是千变万化的,有时可能不是系统所期望的数据,比如用户输入非数字类型等。即使我们认为所有用户输入的数据都是正确的,但是我们还是需要验证用户输入的值。

 

在Erlang-Web中,验证用户输入数据的基本类型是通过wpart_valid模块来实现的,它收集用户的输入数据,并对数据的基本类型进行验证,比如判断一个数据是否是整数类型,或者是否是一个主键等。在Erlang-Web中,验证器是怎么知道这个值的基本类型的呢?在这里,我们可以定义一个自定义的复合类型的记录来申明。

 

首先,我们定义一个是与表结构相同的记录,另外一个是与之对应的记录类型,它描述了各个字段的值类型等。

-record(link,{id,title,uri,text}).
-record(link_types,
        {
        id = {integer, [{description, "Link ID"},{private, true},{primary_key}]},
        title = {string, [{description, "Title"},{min_length, 1}]},
        uri = {string, [{description, "URI http://"},{min_length, 1}]},
        text = {text, [{description, "Description"},{max_length, 255},{rows, 5},{cols, 40}]}
        }
        ).

 

保存这个记录到link.hrl,然后定义与此记录对应的一个wtype文件:

-module (wtype_link).
-export([validate/1, get_record_info/1]).
-include("link.hrl").

get_record_info(link_types) -> #link_types{}
get_record_info(link) -> record_info(fields, link).

validate(From) ->
    SuperField = get_record_info(link),
    SuperType = get_record_info(link_types),
    wpart_valid:validate(SuperField, SuperType, From ++ ["link"]).

 

这个文件的主要作用一是生成一个html页面,二是当用户提交数据时,对用户提交的数据根据link_types来进行验证,不如是否是Int类型,text的值最大长度是否超过255等。其中最后"wpart_valid:validate(SuperField, SuperType, From ++ ["link"])"中的"link"是为了创建一个默认的唯一名称,它代表一个用户自定义的类型,然后用通用工具重新创建它们。函数get_record_info/1的作用是用来保存动态变化类型的,在我们这个例子中,用根据link、link_types,结合起来保存link的各个字段的类型。

 

下面,我们看看Erlang-Web的验证工具是怎么来验证一个int类型的,首先,我们新建一个wtype,命名为wtype_integer,并且导出validate/1函数:

-module (wtype_integer).
-export([validate/1]).

 

validate({Types,Input}) ->
    case wpart_valid:is_private(Types) of
        true ->
            {ok, Input};
        false ->
            case catch list_to_integer(Input) of
                Int when is_integer(Int) ->
                    case check_min(Int, Types) of
                        {ok, Int} ->
                            case check_max(Int, Types) of
                                {ok, Int} -> {ok, Int};
                                ErrorMax -> ErrorMax
                            end;
                        ErrorMin -> ErrorMin
                    end;
            _ -> {error, {not_integer, Input}}
        end
    end.

 

函数的参数被传递进来,并且进行验证。它们始终都是一个元组{Types,Input},Types是从记录link_types中重写的,Input是用户输入的值,它们是与link_types记录中的字段一一对应的。在记录link_types中,我们看到id被定义为private,说明这个字段在页面上是不可见并且不会被用户编辑的。

 

 

上面我们自己编写了一个验证int类型的函数,现在我们看看在控制器中是怎么来验证的。在控制器中,我们不需要像上面那样,自己对用户的输入写函数进行验证,我们可以在dataflow中编写一个验证函数,利用Erlang-Web自带的验证工具来验证用户的输入,下面是代码片段:

 

 dataflow(create) -> [authenticate, validate, validate_logic];

 validate(create,_) ->
    validate_tool:validate_cu(link, create);

 error(create, not_valid) ->
    Err = wpart:fget("__error"),
    Message = "ERROR: Incomplete input or wrong type in form!" ++
    " Reason: " ++ Err,
    wpart:fset("error_message",Message),

    Not_validated = wtype_link:prepare_initial(),
    wpart:fset("__edit", Not_validated),
    {template, "templates/link/add_link.html"};

 

利用dataflow,我们可以很容易的自己创建一个验证器validate,它利用了Erlang-Web的框架工具去调用并且分析来自wpart_valid的响应。只要在验证过程中出现了错误,dataflow将会确保error/2函数被调用,error函数将构建错误信息并且把错误信息用红色标记显示到页面上。下面是完整的代码:

link.hrl

-record(link,{id,title,uri,text}).
-record(link_types,
    {
        id = {integer, [{description, "Link ID"},{private, true},{primary_key}]},
        title = {string, [{description, "Title"},{min_length, 1}]},
        uri = {string, [{description, "URI http://"},{min_length, 1}]},
        description = {text, [{optional,"Description"},{description, "Description"},{max_length, 10000}]}

    }).

 

wtype_link.erl

-module(wtype_link).
-export([validate/1,get_record_info/1]).
-include("link.hrl").

get_record_info(link_types) -> #link_types{};
get_record_info(link) -> record_info(fields,link).

validate(Form) ->
    SuperField = get_record_info(link),
    SuperType = get_record_info(link_types),
   
    wpart_valid:validate(SuperField,SuperType,Form ++ ["link"]).

 

控制器linkAdmin.erl

-module(linkAdmin).
-export([dataflow/1,error/2,validate/2]).
-export([add/1]).
-include("link.hrl").

dataflow(add) -> [validate].

validate(add,_) ->
      validate_tool:validate_cu(link, add).

error(add, not_valid) ->
    Link = wpart:fget("__not_validated"),
    wpart:fset("__edit", wpart_db:build_record_structure(link, Link)),
    {template, "add_link.html"}.

add(Args) ->
    {template, "success.html"}.

 

add_link.html

<html>
  <head>
    <title>Erlang Web Example Page</title>
  </head>
  <body>
    <center>
         <wpart:form type="link" action="/create_link"/>
    </center>
  </body>
</html>

 

dispatch.conf

{static, "^/add_link$", "add_link.html"}.
{dynamic, "^/create_link$", {linkAdmin, add}}.

 

运行效果图:

Erlang-Web的Validation_第1张图片

你可能感兴趣的:(Erlang-Web的Validation)