2

DBIx::ClassMySQL データベースへのアクセスに使用する Catalyst アプリケーションを開発しています。アプリケーションは、ファイルのデータ品質チェックを実行します。ファイルはテーブルにロードされますFileContent:

 FILE_ID LINE_NUMBER FOO BAR BAZ
 -----------------------------------
 1       1           A   99  Blah
 1       2           B   11  Blargh
 1       3           A   4   Sproing
 1       4           B   7   Sproing
 1       5           B   10  Doink

Format次に、各列の検証アクションを定義する別のテーブル があります。

 COL_ORDER COL_NAME VALIDATION
 1         FOO      regex:/^[AB]$/
 2         BAR      unique_number
 3         BAZ      regex:/\S/

私がやりたいことは、特定のファイルを 1 行ずつFileContent調べて、すべてのルールを各行に適用することです。Format

my @lines  = $c->model('DB::FileContent')->search({file_id => 1});
my @format = $c->model('DB::Format')->search();

foreach my $line (@lines)
{
    foreach my $column (@format)
    {
        #Get the field matching this column from $line.
        #e.g. for first $column get $line->foo()  
    }
}

ただし、フォーマットの現在の列に一致する行から列を効率的に取得する最善の方法がわかりません。列にアクセスする通常の方法は、 などのメソッドを使用すること$line->fooです。しかし、変数が変数の場合はどうすればよいfooでしょうか?

私はこれをしたいとは思わない:

eval "$line->${$column->col_name}";

get_column は知っていますが、これは行から単一の値を取得するのに効率的ですか?

$line->get_column($column->col_name)

他のテーブルの値に基づいて列を取得する最も効率的な方法は何ですか? 列名または列位置のいずれかを使用できます。よろしくお願いします。

4

1 に答える 1

2

最初にすべての検証ルールを hashref (またはハッシュ) に入れてみてください。そして最も重要なのは、 FileContent アイテムがDBIx::Class::ResultClass:: HashRefInflator を介して hashref にインフレートされることを確認することです。これにより、アイテム内のフィールドを循環してアクセスするのがはるかに便利になります。

このような:

#------------------------------------------------------------------------------------------
# get all formats into a hashref
#------------------------------------------------------------------------------------------

my $format = $c->model('DB::Format')->search({}, { order_by => ['COL_ORDER'] } );
my @col_names = $format->get_column('COL_NAME')->all;
# @col_names now contains qw/FOO BAR BAZ/

my $formats;
@{$formats}{@col_names} = $format->get_column('VALIDATION')->all;

#------------------------------------------------------------------------------------------
# create an iterator over DB::FileContent, and make items inflate to hashrefs 
#------------------------------------------------------------------------------------------

my $file_content  = $c->model('DB::FileContent')->search({file_id => 1});
$file_content->result_class('DBIx::Class::ResultClass::HashRefInflator');
# this ensures that every item inflates into a hashref


# this way you can iterate over items, and don't have to put them all into an array 
while (my $hashref = $file_content->next) {
    # put relevant field values into an array
    my @values = @{$hashref}{@col_names};
}
于 2013-03-18T19:09:16.830 に答える