Meadows of wild horses

Blog...

Net::Twitter

| Comments

Net::Twitter 설치시 실패

서버에 모듈을 설치 하려고 하는데 자꾸 실패 하게 되었다. ssl도 있고 Dev도 있는데 왜?? 그건 libssl-dev가 없어서 였다

Month-split

| Comments

user의 아이디를 가지고 elapsed_at 의 내용을 가져 오게 된다 이 값은 2012-09-09 21:00:00 형식으로 되어 있으며 2012 와 09 를 기준으로 값을 따로 가지게 하여년도별 월 횟수를나타나게 해주었다 하지만 필요 없어 지움…

controll

$cond = {} if %$cond;

my $user_id;
if ($id) {
    $user_id = $user_info->id;
}
else {
    $user_id = $c->user->id;
}

$cond->{'me.user_id'} = $user_id;

my %attr            = ( 'order_by' => { -desc => 'me.elapsed_at' } );

my $activity_search = $c->model('BikeMeDB')->resultset('Activity')->search($cond, \%attr);
my $activities      = [ $activity_search->all ];
my $activity_data   = {};

for my $activity (@{ $activities }) {
    my $year;
    my $month;

    my $elapsed = $activity->elapsed_at;
    $year       = $activity->elapsed_at->year;
    $month      = $activity->elapsed_at->month;

    my @split_elapsed = split('-', $activity->elapsed_at, 3);

    $activity_data->{$split_elapsed[0]}{$split_elapsed[1]}++;
}

my $year  = $c->req->params->{year};
my $month = $c->req->params->{month};

my $max_year  = '00000';
my $max_month = '00';

if ($year && $month) {
    $max_year  = $year;
    $max_month = $month;
}
else {
    foreach my $year (keys %$activity_data) {
        if ($year gt $max_year) {
            $max_year = $year;
        }
        else {
            $max_month = '00';
            last;
        }

        foreach my $month (keys $activity_data->{$year}) {
            $max_month = $month if $month gt $max_month;
        }
    }
}

$cond = {} if %$cond;
$cond->{'me.user_id'} = $user_id;
$cond->{'me.elapsed_at'} = { 'like', "%"."$max_year"."-"."$max_month"."%" };

$activity_search = $c->model('BikeMeDB')->resultset('Activity')->search($cond, \%attr);

view - 년-월

[% FOEACH year IN activity_data.keys.reverse %]
    [% FOREACH month IN activity_data.$year.keys.sort.reverse %]
  <div class="btn">
    <a href="[% c.uri_for('/activities') %]?year=[% year %]&month=[% month %]" class="btn btn-primary">[% year %]-[% month %] ([% activity_data.$year.$month %])</a>
</div>
    [% END %]
[% END %]

Catalyst-test-code

| Comments

Web - Catalyst Test Code 작성

Catalyst로 웹을 구축 하던중 테스트 코드를 작성을 부여 받았습니다. 테스트 코드를 진행 하기 위한 모듈을 적습니다.

모듈

Test::More

기본 적이 펄 테스트 코드 문법을 확인 할수 있습니다.

Catalyst::Test

content, response 페이지 정보를 얻어 올수 있습니다.

HTTP::Response

response 정보등을 확인 할수 있습니다.

URI

response 정보등을 확인 할수 있습니다.

HTTP::Request::Common

Get POST 등을 구현 할수 있습니다.

CGI::Simple::Cookie

로그인 인증 관련 세션 처리를 할수 있습니다.

HTTP::Cookies

CGI::Simple::Cookie로 쿠키 관련 재설정이 반복 되며 번거로울때 파일로 저장하여 사용할수 있다.

## 첫번째 t 파일에서 login 하고 cookie 를 저장해둔다. pull/109설명중.
my $cookies = HTTP::Cookies->new(file => 't/.cookies');
# res & res
$cookies->extract_cookies($res);
$cookies->save;

## 다른 t 파일에서는..
my $cookies = (split(/:/, HTTP::Cookies->new(file => 't/.cookies')->as_string))[1];

Export_csv

| Comments

목차

  1. CSV 출력 준비
  2. View 생성

CSV 출력 준비

선택된 내역을 출력 하기 위한 버튼을 추가한다.

root/templates/bootstrap/src/deposit/index.tt

1
  <a class="btn btn-primary" id="do_export">출력</a>

선택된 내역 js처리

root/static/scripts/list.js

1
2
3
4
5
6
7
8
9
10
  $('#do_export').click(function() {
    var selected_charges = [];

    $('#charge_list tr').filter(':has(:checkbox:checked)').each(function(){
      if($(this).attr('id') !== undefined)
        selected_charges.push($(this).attr('id'))
    });

    location.href = '/deposit/export/' + selected_charges;
  });

Sil/Web/Don/Controller/Deposit.pm

선택된 승인 내역을 CSV로 출력하기 위하여 모듈 - Catalyst::View::Download::CSV을 사용 하였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sub export :Local CaptureArgs(1) {
    my ( $self, $c, $id ) = @_;
    my @target_ids = split ',', $id;
    
    my @charges;
    
    push @charges, ['제목', '청구자', '금액', '영수증날짜'];
    
    foreach my $charge($c->model('DonDB')->resultset('Charge')->search({id => { -in => \@target_ids }})->all) {
        push @charges, [ $charge->title, $charge->user->user_name, $charge->amount, $charge->usage_date];
    }

    if (@charges) {
        $c->stash->{'csv'} = { 'data' => [ @charges ] };
        $c->flash->{messages} = 'Success Exported.';

    } else {
        $c->flash->{messages} = 'Export Failed.';
    }
    $c->forward('Sil::Web::Don::View::Download::CSV');
}

View 생성

View는 script_web_don_create view로 생성한다.

list/Sil/Web/Don/View/Download/CSV.pm을 생성 완료.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package Sil::Web::Don::View::Download::CSV;
use Moose;
use namespace::autoclean;

extends 'Catalyst::View::Download::CSV';

=head1 NAME

Sil::Web::Don::View::Download::CSV - Catalyst View

=head1 DESCRIPTION

Catalyst View.

=head1 AUTHOR

ja3ck

=head1 LICENSE

This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

__PACKAGE__->meta->make_immutable;

1;

DB_Password_Hash

| Comments

DB Password HASH

DBIx::Class::EncodedColumn

기본 입력값 입력시 sha(‘password’)사용 하여 암호화 할수 있도록 한다.

1
INSERT INTO `user` VALUES (2,'rum_user','rum_user@mail.com',sha('Password'),localtime ,localtime);

MyWeb::ResultBase.pm에 EncodedColumn 추가하여 준다.

1
2
3
4
5
__PACKAGE__->load_components(qw/
    EncodedColumn
    InflateColumn::DateTime
    TimeStamp
/);

Catalyst::Plugin::Authentication

my_web.conf 파일에 플러그인 설정 추가 pawword_type 설정시 디폴트로 SHA-1이 적용되지만 명시적으로 password_hash_type을 정의 하여 준다.

1
2
3
4
5
6
7
8
<Plugin::Authentication>
    <default>
        password_type      hashed
        password_hash_type SHA-1
        user_model         DonDB::User
        class              SimpleDB
    </default>
</Plugin::Authentication>

설정 추가 참고 자료

Catalyst::Authentication::Credential::Password

Digest

Don-Change-space

| Comments

Sil::Web::Don 변경

Sil::Schema는 Sil의 공용 스키마가 아닌데도 불구 하고 그렇게 보일수도 있는 상태 이다 이를 바꾸기 위해서 Sil::Don::Schema로 바꾼다. 이는 Sil의 Don만의 스키마라고 명시 해주는것과 같다.

변경전

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
lib
`-- Sil
    |-- Schema
    |   |-- Result
    |   |   |-- Charge.pm
    |   |   `-- User.pm
    |   `-- ResultBase.pm
    |-- Schema.pm
    `-- Web
        |-- Don
        |   |-- Controller
        |   |   |-- Deposit.pm
        |   |   |-- List.pm
        |   |   |-- Login.pm
        |   |   |-- Logout.pm
        |   |   `-- Root.pm
        |   |-- Model
        |   |   `-- DonDB.pm
        |   `-- View
        |       |-- Bootstrap.pm
        |       `-- Download
        |           `-- CSV.pm
        `-- Don.pm

변경후

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 lib
└── Sil
    └── Don
        ├── Schema
        │   ├── Result
        │   │   ├── Charge.pm
        │   │   └── User.pm
        │   └── ResultBase.pm
        ├── Schema.pm
        ├── Web
        │   ├── Controller
        │   │   ├── Deposit.pm
        │   │   ├── List.pm
        │   │   ├── Login.pm
        │   │   ├── Logout.pm
        │   │   └── Root.pm
        │   ├── Model
        │   │   └── DonDB.pm
        │   └── View
        │       ├── Bootstrap.pm
        │       └── Download
        │           └── CSV.pm
        └── Web.pm

경로명 변경

의존성이 걸려있는 모든 내역들을 grep 명령어로 찾아 아래와 같이 수정해 주었다.

변경전

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Sil::Schema::Result::Charge
Sil::Schema::Result::User
Sil::Schema::ResultBase
Sil::Schema

Sil::Web::Don::Controller::Deposit
Sil::Web::Don::Controller::List
Sil::Web::Don::Controller::Login
Sil::Web::Don::Controller::Logout
Sil::Web::Don::Controller::Root
Sil::Web::Don::Model::DonDB
Sil::Web::Don::View::Bootstrap
Sil::Web::Don::View::Download::CS
Sil::Web::Don

변경후

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Sil::Don::Schema::Result::Charge
Sil::Don::Schema::Result::User
Sil::Don::Schema::ResultBase
Sil::Don::Schema

Sil::Don::Web::Controller::Deposit
Sil::Don::Web::Controller::List
Sil::Don::Web::Controller::Login
Sil::Don::Web::Controller::Logout
Sil::Don::Web::Controller::Root
Sil::Don::Web::Model::DonDB
Sil::Don::Web::View::Bootstrap
Sil::Don::Web::View::Download::CS
Sil::Don::Web

변경후 문제점

내용 수정후 서버 실행이 app.psgi에서 모듈을 찾지 못한다고 하였다. 이유는 Sil_web_Don.conf 파일명을 수정 해주지 않았기에 발생한 문제였다. 경로명이 바뀌엇듯이 파일명도 교체 해주어야 한다.

Don Release

| Comments

Donnenwa Open

  1. DNS 요구
  2. Apache2 설정
  3. supervisior 설정
  4. 확인

DNS 요구

도메인 네임을 받아 현진이(서버)에 연결해 주어야 하지만 브롬튼에 도메인이 정의가 되있기 때문에 SE님에게 요구하면 된다.(나만되는겨)

Apache2 설정

1
2
3
4
5
6
7
8
$ ssh rumidier@bu….접속
$ cd /etc/apache2/
$ cd sites-available
$ vi user.site.kr (작성)
$ cd ../
$ cd sites-enable
$ ln -s 타킷-경로
$ ~/etc/init.d/apache2 restart

supervisior 설정

슈퍼 바이저는 서버가 죽었다 다시 살아 났을시 수동이 아닌 자동으로 서버를 뛰워주기 위해 필요한 기능이다.

돈내놔는 carton을 사용하고 plackup으로 뛰우며 플라넥스와는 다르게 worker의 갯수가 존재 하지 않는다. 포트 설정은 아파치에서 해준 포트를 명시 해준후 디렉토리와 유저, 환경 등록을 해주면 끝이 난다. 환경경로는 carton과 plackup 경로도 알아야 하는거 같다(이 부분은 설명이 더 필요)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ cd /etc
$ vi supervisord.conf

[program:Donnenwa] 
command=/usr/local/bin/carton exec -Ilib -- /home/USER Donnenwa/local/bin/plackup -Ilib -a /home/USER/Donnenwa
app.psgi --host 127.0.0.1 --port You_port(ex:3000)  
directory=/home/User/Donnenwa 
user=USER 
environment=PATH=/usr/local/bin:/usr/bin:/bin,HOME=/home/USER
stdout_logfile=/home/USER/logs/stdout 
stderr_logfile=/home/USER/logs/stderr 

$ sudo supervisorctl
supervisor> status
….
supervisor> update
supervisor> exit
$ 서버 실행 확인 끝

더 물어 봐야 할것

  1. supervisor의 셋팅을 무엇을 참조 하는가?
  2. 도메인 등록은 어떻게 하는가?
  3. apach2 설정은 어떻게 하는가?

Side-function

| Comments

Action - approval, refuse

approval

refuse

Approval은 청구 목록에 대하여 승인 기능을 refuse는 청구 목렉에 대하여 거부 기능을 가지게 된다.

승인 기능은 두가지 상황에서 선택 할수 있게 된다. /list/view/user_num과 전체 list상태, 대기 리스트 상태, 거부 리스트 상태 에서 활성화가 되고 action을 취할수 있게 한다.

거부 기능은 두가지 상황에서 선택 할수 있게 된다. /list/view/user_num과 전체 list상태, 대기 리스트 상태, 승인 리스트 상태 에서 활성화가 되고 action 을 취할수 있게 한다.

/list/view/user_id

아래와 같이 id 값과 함께 전달 할수 있다.

<a href="[% c.uri_for('/list/approval', charge.id) %]" class="btn btn-primary">승인</a>
<a href="[% c.uri_for('/list/refuse', charge.id) %]" class="btn btn-primary">거부</a>

CaputreArgs(1) 옵션으로 $id 값(들)을 받을수 있게 된다.

sub approval :Local :CaptureArgs(1) {
    my ( $self, $c, $id ) = @_;
    my @target_ids = split ',', $id;

sub refuse :Local :CaptureArgs(1) {
my ( $self, $c, $id ) = @_;
my @target_ids = split ',', $id;

@target_id의 모든 값(들)을 status값이 2 or 3로 업데이트 한다. 업데이트는 검색을 한 값들을 대상으로 update를 하게 된다.

$ vi root/templates/default/src/list

# 승인
my $approval = $c->model('MyApp_DB')->resultset('Charge')->search({ id => { -in
        => \@target_ids } })->update_all({ status => '2' });
# 거부
my $refuse = $c->model('MyApp_DB')->resultset('Charge')->search({ id => { -in
        => \@target_ids } })->update_all({ status => '3' });

flash기능으로 messages값을 전달하여 조건에 맞을시 메세지를 출력 시키도록 한다.(/list/index.tt 참고) 조건은 approval, refuse기능이 정상 작동 되었는지를 검사 하게 된다.

if ($query_status) {
    $c->flash->{messages} = 'Success message.';
}
else {
    $c->flash->{messages} = 'No status Item.';
}

템플릿에 쓰일 status값과 함께 전체 목록으로 redirect 시키도록 한다.

$c->stash->{status} = '2'; #상태에 맞는 status값
$c->res->redirect($c->uri_for('/list'));

Action - delete

delete

승인 기능은 두가지 상황에서 선택 할수 있게 된다. /list/view/user_num과 전체 list상태, 대기, 거부, 수정 상태 에서 활성화가 되고 action을 취할수 있게 한다.

$ vi root/templates/default/src/list
<a href="[% c.uri_for('/list/delete', charge.id) %]" class="btn btn-primary">삭제</a>

다른 기능과 같이 CaptureArgs(1)를 받는다.

sub delete :Local :CaptureArgs(1) {
my ( $self, $c, $id ) = @_;
my @target_ids = split ',', $id;

다른 기능과 달리 update_all 이 아닌 delete_all를 통하여 내용을 삭제 한다.

my $charge = $c->model('DonDB')->resultset('Charge')->search({ id => { -in => \@target_ids } })->delete_all;

CPAN

DBIx::Class::Manual::DocMap