Jeen - Yet anothere techlog

STFUAWSC

Building a Perl Project on Travis CI

Travis CI은 이전에 얘기를 들었을 때는 별 관심이 없었는데(처음에는 확실히 Perl 을 지원하지 않아서), 언제부턴가 Perl 을 지원한다는 얘기를 듣고 Perl 커뮤니티에서 움직임이 조금씩 있더라구요. Dist::Zilla::TravisCI 같은 모듈들도 나오는 걸로 봐서…

사용하는 방법은 아주 간단합니다. Github 계정에 연결되고, 그리고 Github 의 Public 상태의 프로젝트를 고르고… 그 프로젝트에 .travis.yml 파일을 놓아주면 됩니다.

자세한 건 위의 설명페이지를 참고해서 이전에 살짝 만들어 놓은 ZamakistTravis CI 에서 돌려보게 해봤습니다.

img-failed

처음에야 뭐 물론 .travis.yml 파일이 없어서 실패했다는 메일이 날라왔구요.

.travis.yml 을 추가해준 결과로는 다시 이렇게 제대로 돌아간다는 메일이 옵니다.

Img1

Travis CI 에서 출력되는 빌드 내용은 아래와 같습니다.

~~~ bash Using worker: ppp3.worker.travis-ci.org:php-1

$ cd ~/builds $ git clone —depth=100 —quiet git://github.com/JEEN/p5-App-Zamakist.git JEEN/p5-App-Zamakist $ cd JEEN/p5-App-Zamakist $ git checkout -qf df10bdfea286c9933c345c84206eaa90b8f298a6 $ perlbrew use 5.16 $ perl —version

This is perl 5, version 16, subversion 0 (v5.16.0) built for i686-linux

Copyright 1987-2012, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on this system using “man perl” or “perldoc perl”. If you have access to the Internet, point your browser at http://www.perl.org/, the Perl Home Page.

$ cpanm —version cpanm (App::cpanminus) version 1.5017 $ cpanm —quiet —installdeps —notest . Successfully installed Text-CharWidth-0.04 Successfully installed Text-UnicodeBox-0.03 Successfully installed XML-XPathEngine-0.13 Successfully installed HTML-Tree-5.02 Successfully installed HTML-TreeBuilder-XPath-0.14 Successfully installed HTML-Selector-XPath-0.14 Successfully installed Web-Query-0.08 Successfully installed Term-ReadLine-Zoid-0.07 8 distributions installed $ perl Makefile.PL && make test include /home/travis/builds/JEEN/p5-App-Zamakist/inc/Module/Install.pm include inc/Module/Install/Metadata.pm include inc/Module/Install/Base.pm include inc/Module/Install/Makefile.pm Cannot determine perl version info from lib/App/Zamakist.pm include inc/Module/Install/Scripts.pm include inc/Module/Install/Include.pm include inc/Test/More.pm include inc/Module/Install/WriteAll.pm include inc/Module/Install/Win32.pm include inc/Module/Install/Can.pm include inc/Module/Install/Fetch.pm Writing Makefile for App::Zamakist Writing MYMETA.yml and MYMETA.json Writing META.yml cp lib/App/Zamakist/Media.pm blib/lib/App/Zamakist/Media.pm cp lib/App/Zamakist.pm blib/lib/App/Zamakist.pm cp lib/App/Zamakist/Role/Reportable.pm blib/lib/App/Zamakist/Role/Reportable.pm cp lib/App/Zamakist/Handler/GOM.pm blib/lib/App/Zamakist/Handler/GOM.pm cp bin/zamakist blib/script/zamakist /home/travis/perl5/perlbrew/perls/5.16/bin/perl “-Iinc” -MExtUtils::MY -e ‘MY->fixin(shift)’ — blib/script/zamakist PERL_DL_NONLAZY=1 /home/travis/perl5/perlbrew/perls/5.16/bin/perl “-MExtUtils::Command::MM” “-e” “test_harness(0, ‘inc’, ‘blib/lib’, ‘blib/arch’)” t/*.t t/00_compile.t ……… ok t/01_find_permalink.t .. 5/7 # http://search.gomtv.com/searchjm.gom?key=The.Mentalist.S04E01.HDTV.XviD-ASAP.%5BVTV%5D.Scarlet.Ribbons&preface=0 # http://gom.gomtv.com/jmdb/view.html?intSeq=808364&preface=0&spage=1 Wide character in print at /home/travis/perl5/perlbrew/perls/5.16/lib/5.16.0/Test/Builder.pm line 1759. # [통합] The.Mentalist.S04E01.HDTV.XviD-ASAP t/01_find_permalink.t .. ok All tests successful. Files=2, Tests=8, 10 wallclock secs ( 0.03 usr 0.01 sys + 1.79 cusr 0.10 csys = 1.93 CPU) Result: PASS

Done. Build script exited with: 0 ~~~

좀 더 뭐 욕심이 있다면 Jenkins 에서 처럼 정적분석이나 테스트 케이스에 대해서 좀 더 자세한 내용이 나와줬으면 좋겠다 싶지만… 사실 그건 뽀대의 문제라…

위의 빌드 내용에 대한 자세한 내용은 아래의 링크를 참고하세요.

DBIx::Class and JSON

흔한 웹서비스의 흔한 AJAX 나 흔한 RESTful API 를 제공하기 위해서, 대개 JSON 포맷의 데이터를 서버에서 뿜어내고는 합니다.

하지만 누구나가 Catalyst + DBIx::Class 조합에서 이렇게 하면 되는 게 아닐까 하고 접근했다가…

… encountered object ‘..’, but neither allow_blessed nor convert_blessed settings are enabled …

라는 에러를 접하게 됩니다. bless 된 오브젝트를 어떻게든 JSON 인코딩을 시도하려고 했을 때는 위와 같은 에러를 쉬이 접할 수 있습니다.

이것을 푸는 방법은 사실 여러가지가 있습니다.

이것저것 신경쓰지 말고 한번에 가자고 할 때는 Catalyst::View::JSON 에서 인코딩하게 되는 stash 된 값들을 전부 ArrayRef 나 HashRef 로 변환해서 넘기는 방법입니다.

~~~ perl my @data; my $rs = $c->model(‘DB’)–>resultset(‘User’)–>search(); while(my $row = $rs->next) {

   push @data, {
       id => $row->id,
       name => $row->name,
       created_at => $row->created_at,
   };

} $c->stash->{people} = \@data; ~~~

위처럼 특정컬럼을 선별해서 넣어주는 방법이 있겠지요. 좀 더 단순화한다면, 각 스키마테이블 별로 HashRef 를 반환하는 메소드를 넣어두는 것도 좋습니다.

~~~ perl lib/MyApp/Schema/Result/User.pm sub to_hashref {

my $self = shift;
return {
    id => $self->id,
    name => $self->name,
    created_at => $self->created_at,
};

}

# Controller my @data; my $rs = $c->model(‘DB’)–>resultset(‘User’)–>search(); while(my $row = $rs->next) {

   push @data, $row->to_hashref;

} $c->stash->{people} = \@data; ~~~

~~~ perl my $person = $c->model(‘DB’)–>resultset(‘User’)–>search($cond, {

  result_class => 'DBIx::Class::ResultClass::HashRefInflator',

})–>first; $c->stash->{person} = $person; ~~~

그럴 필요가 없다면 위처럼 result_class 를 지정해줌으로써 결과를 무조건 HashRef 로 반환하게끔 합니다.

사실 DBIx::Class::ResultClass::HashRefInflator 를 적용하면 일일이 오브젝트를 만들어내지 않기 때문에 퍼포먼스 측면에서 매우 좋습니다만, 그냥 HashRef 일 따름인지라Resultset 에서 정의한 각종 메소드를 참조할 수 없습니다.

그러니 이런저런 경우에는 가려서 사용하는 것이 좋습니다.

이제 본질적으로 좀 더 접근해보면… JSON::XS 는 인코딩할 시에, 오브젝트가 대상인 경우에는 해당 오브젝트의 TO_JSON 메소드를 참조하여 결과를 뽑아낼 수 있습니다. 물론 allow_blessed, convert_blessed 플래그를 지정할 필요가 있지요.

~~~ perl

lib/MyApp/View/JSON.pm

package MyApp::View::JSON; use JSON::XS ();

use parent qw(Catalyst::View::JSON);

my $encoder = JSON::XS->new

          ->utf8
                      ->pretty(0)
                      ->indent(0)
                      ->allow_blessed(1)
                      ->convert_blessed(1);

sub encode_json {

my ($self, $c, $data) = @_;
$encoder->encode($data);

}

1; ~~~

그러면 위처럼 encode_json 을 오버라이드합니다. allow_blessedconvert_blessed 플래그를 켜주는 것이죠.

~~~ perl

lib/MyApp/Schema/Result/User.pm

.. sub TO_JSON {

return { $_\[0\]->get_inflated_columns };

} .. ~~~

그리고 위처럼 User Result 에 대해서 TO_JSON 를 지정합니다.

perl $c->stash->{people} = [ $c->model(‘DB’)–>resultset(‘User’)–>search()–>all ];

그러면 이제는 아무런 걱정없이 그냥 생짜 DBIC Resultset 을 날려버려도 이제는 알아서 문제해결이 됩니다. :–)

각 Resultset 마다 TO_JSON 을 지정하기가 벅차다면…

위의 글에서 ResultBase 를 참고해주세요.

MyApp::Schema::ResultBase 를 상속받은 각 Result 테이블들은 TO_JSON 을 오버라이드 해서 빼놓고 싶은 컬럼(예를 들어 password 같은 컬럼) 을 배제해서 출력할 수 있지 않을까요?

Moving From Bash to Zsh Again

밥벌이도구가 바뀌고 해서 다시 ZSH 로 돌아갔습니다.

지난번에 MacBook Air 에 올리다가 뭐가 꼬인 YADR 을 썼습니다. grep 경고메시지가 없이 깔끔하게 돌아가는 군요.

이래저래 개발환경도 맞추고 그러다가 지난달에 zsh 5.0 이 릴리즈 된 것을 보고 Mt.LION 에 깔린 zsh 버젼을 확인하니..

bash $ zsh —version zsh 4.3.11 (i386-apple-darwin12.0)

4.3.11 이었습니다. 그래서 zsh 5.0 으로 올려보려고 brew 로 일단 깔았죠.

그리고 chsh 로 셸을 바꾸려고 하는 데…

bash $ chsh -s /usr/local/bin/zsh Changing shell for jeen. Password for jeen: chsh: /usr/local/Cellar/zsh/5.0.0/bin/zsh: non-standard shell

이라고 뜨는 것이었지요.

구글검색결과 /etc/shells 에 해당 셸의 패스를 추가하는 것으로 이 난관을 헤쳐나갈 수 있다고 합니다.

그래서 네. zsh 5.0 쓰고 있는데 뭐가 좋은지는 써보면서 느끼게 되려나요.

이런 CHANGELOG 도 일단 보고 있지만요…