2011年8月28日日曜日

plalaのOP25B対策、sendmail編

plalaのOP25B対策、sendmail編,centos
# vi /etc/mail/sendmail.mc
dnl define(`SMART_HOST', `smtp.your.provider')dnl ←この行のしたに
define(`SMART_HOST', `esmtp:[timmy.mail.plala.or.jp]')dnl
↑「timmy」の部分は個人差がある、契約書で確認
define(`ESMTP_MAILER_ARGS',`TCP $h 587')←追加
FEATURE(authinfo, DATABASE_MAP_TYPE` -o 'MAIL_SETTINGS_DIR`authinfo')←追加
↑上記三行を追加、:wqで保存
# yum -y install sendmail-cf
# m4 /usr/share/sendmail-cf/m4/cf.m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
# telnet timmy.mail.plala.or.jp 587
Trying 58.93.xxx.xx...
Connected to timmy.mail.plala.or.jp (58.93.xxx.xx).
Escape character is '^]'.
220 msa0Xx.plala.or.jp ESMTP server ready Fri, 12 Aug 2011 23:16:05 +0900

ehlo localhost ←情報を出力
250-msa0Xx.plala.or.jp
250-AUTH=LOGIN PLAIN CRAM-MD5 ←認証方法
250-AUTH LOGIN PLAIN CRAM-MD5
250-PIPELINING
250-DSN
250-8BITMIME
250 SIZE 20971520
quit ←一旦出る
221 msa0Xx.plala.or.jp ESMTP server closing connection
# echo AuthInfo:timmy.mail.plala.or.jp \"U:ユーザ名\" \"P:パスワード\" \"M:認証方法\" > /etc/mail/authinfo
※ここの「LOGIN PLAIN CRAM-MD5」は先情報出力時の認証方法
※アカウント名とパスワードは契約書で確認、アカウント名は「@」前の部分

# chmod 640 /etc/mail/authinfo
# makemap hash /etc/mail/authinfo.db < /etc/mail/authinfo # chgrp smmsp /etc/mail/authinfo.db # /etc/rc.d/init.d/sendmail reload sendmail を再読み込み中: [ OK ]
sm-client を再読み込み中: [ OK ]

2011年8月26日金曜日

vbaでcsvを一気にScripting.Dictionaryに格納する方法、セル内改行やダブルクォーテーションエスケープ対応版

vbaでcsvを読み込む方法が2つあると思う

一つ目:
テキストとして一行つづ読んで、区切りコンマまたはタブでsplitして処理する、この方法はメリットは高速で簡単、デメリットはフィルド内改行やダブルクォーテーションがあったら、おかしくなること

二つ目:
Workbookでcsvを開き、range単位で処理する方法。方法1と比べてちょっと遅いですが、Excelで正常に開けるCSVなら、問題なく処理できるというのはポイント。※注意:連想配列Scripting.Dictionaryを使うには、「ツール」⇒「参考設定」の中に「Microsoft Scripting Runtime」をチェック入れてね

それでは2番目の方法を紹介します:

例えばこんなCSVがあります

名前 学校名 学年 クラス 国語 英語 数学
田中 一小 3年 1組 90 80 70
佐藤 ニ小 3年 1組 34 60 90
渡辺 一小 2年 2組 78 76 80
田中 ニ小 1年 3組 66 66 78
中田 一小 2年 1組 67 89 53
山田 ニ小 3年 2組 43 57 78


まずは一個モジュールを作りましょう。例えば名前はcsv_reader。内容は下記:
Option Explicit
Public gReits As New Scripting.Dictionary '格納先の連想配列
Sub CSV_Read2()
    Dim FileType, Prompt As String
    Dim FileNamePath As Variant
    Dim dicHeader As New Scripting.Dictionary
    Dim dicHeaderRev As New Scripting.Dictionary
    Dim wb As New Workbook
    Dim st As New Worksheet
    Dim csvrow As Range
    Dim csvfield As Range
    Dim strFolder As String
    
    Dim FSO As Object
    
    'まずはcsvファイルを選択するダイアログボックス
    FileType = "CSV ファイル (*.csv),*.csv"
    Prompt = "CSV File を選択してください"
    
    '操作したいファイルのパスを取得します
    FileNamePath = SelectFileNamePath(FileType, Prompt)

    'キャンセルボタンが押された
    If FileNamePath = False Then
        End
    End If
    
    '格納先の連想配列を空にする
    gReits.RemoveAll
    
    'csvファイルを開く
    Set wb = Workbooks.Open(FileNamePath)
    'シートをセット(csvファイルはsheet1しかない)
    Set st = wb.Sheets(1)
    '内容の有るすべてのレンジから一行つづ読み込む
    For Each csvrow In st.UsedRange.Rows
        '一行目はタイトル、タイトル変数に格納
        If csvrow.row = 1 Then
            'タイトル行のすべての列
            For Each csvfield In csvrow.Columns
                'タイトル名と列の情報をkey,item交代でそれそれ格納し
                dicHeader.Add csvfield.Value, csvfield.Column
                dicHeaderRev.Add csvfield.Column, csvfield.Value
            Next
        Else
            '2行目以降の処理
            '今後使うときにやりやすいようにデータは階層構造として格納する
            '第一階層キーはcsvの学校の値
            '第二階層キーは学年
            '第三階層キーはクラス
            '第四階層キーはなく、csvの生徒のデータを格納する場所
            
            'もし第一階層キーまだ登録してなければ登録します
            If Not gReits.Exists(Cells(csvrow.row, dicHeader.Item("学校名")).Value) Then
                gReits.Add Cells(csvrow.row, dicHeader.Item("学校名")).Value, New Scripting.Dictionary
            End If
            
            'もし第ニ階層キーまだ登録してなければ登録します
            If Not gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Exists(Cells(csvrow.row, dicHeader.Item("学年")).Value) Then
                gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Add Cells(csvrow.row, dicHeader.Item("学年")).Value, New Scripting.Dictionary
            End If
            
            'もし第三階層キーまだ登録してなければ登録します
            If Not gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Item(Cells(csvrow.row, dicHeader.Item("学年")).Value).Exists(Cells(csvrow.row, dicHeader.Item("クラス")).Value) Then
                gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Item(Cells(csvrow.row, dicHeader.Item("学年")).Value).Add Cells(csvrow.row, dicHeader.Item("クラス")).Value, New Scripting.Dictionary
            End If
            
            '最後列ごとで、タイトルと値を連想配列に格納する
            For Each csvfield In csvrow.Columns
                gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Item(Cells(csvrow.row, dicHeader.Item("学年")).Value).Item(Cells(csvrow.row, dicHeader.Item("クラス")).Value).Add dicHeaderRev.Item(csvfield.Column), csvfield.Value
            Next
            
        End If
    Next
    wb.Close SaveChanges:=False
    set wb = nothing
    set st = nothing
    'ここまで、csvのデータがすべてグローバル連想配列変数gReitsに格納したはず、あとは好きなように使うだけ
    call printOut
End Sub
Function SelectFileNamePath(FileType, Prompt) As Variant
  SelectFileNamePath = Application.GetOpenFilename(FileType, , Prompt)
End Function

Sub printOut()
    Dim gakkou As Variant
    Dim gakunen As Variant
    Dim class As Variant

    If gReits.Count > 0 Then
        For Each gakkou In gReits.Keys
            Debug.Print "学校名:" & gakkou
            For Each gakunen In gReits.Item(gakkou).Keys
                Debug.Print vbTab & "学年:" & gakunen
                For Each class In gReits.Item(gakkou).Item(gakunen).Keys
                    Debug.Print vbTab & vbTab & class
                    Debug.Print vbTab & vbTab & vbTab & gReits.Item(gakkou).Item(gakunen).Item(class).Item("名前") & "⇒" & _
                                                        "国語:" & gReits.Item(gakkou).Item(gakunen).Item(class).Item("国語") & _
                                                        "英語:" & gReits.Item(gakkou).Item(gakunen).Item(class).Item("英語") & _
                                                        "数学:" & gReits.Item(gakkou).Item(gakunen).Item(class).Item("数学")
                Next
            Next
        Next
    End If

End Sub
イミディエイトウィンドウの出力はこんな感じ 学校名:一小
  学年:3年
    1組
      田中⇒国語:90英語:80数学:70
  学年:2年
    2組
      渡辺⇒国語:78英語:76数学:80
    1組
      中田⇒国語:67英語:89数学:53
学校名:ニ小
    学年:3年
    1組
      佐藤⇒国語:34英語:60数学:90
    2組
      山田⇒国語:43英語:57数学:78
    学年:1年
    3組
      田中⇒国語:66英語:66数学:78

Ruby on Rails DateTimeやTimeオブジェクトの比較謎

データベースにavailable_toというdatetime型のフィルドがあります
active recordのfindメッソドを使って取り出した時は値の型は何でしょうか?

railsのバージョンによるかもしれないが、少なくでもrails1.16ではDateTime
やTimeオブジェクトと直接比較できなかった、謎!


if rec.available > DateTime.now
comparison of Time with DateTime failed
怒られました!なんで??
findメソッドを経由して、型が変わった?そんなわけないだろう...
取り敢えずこうして見る
if rec.available > Time.now
comparison of DateTime with Time failed
え?!冗談でしょう!
...仕方がない、最後の一撃!
if rank.fund.available_to.to_s.to_date > DateTime.now.to_s.to_date
やっと出来た...激汚いですけど

仕方がない、そして謎が一杯残ってます...
取り敢えず忘れよう。うん!

RailsのactiveRecordのfindメッソドで複数テーブル(Join)からクエリー

fund(1)<------>(*)fund_ranking
fundとfund_rankingは一対多の関係です。キーはfund_rankingsテーブルのfund_id
まずはmodelsでそれぞれ関係を作りましょう
fund.rbに追加
has_many :fund_rankings #ここは複数形
fund_ranking.rbに追加
belongs_to :fund #ここは単数形
ここで単数複数を間違うとActiveRecord::ConfigurationError と怒られる
コントローラー側 fund/ranking_controller.rb
@pcipu1m = FundRanking.find :all,
               :conditions => ["yyyymm = ? and period = '1m'", @yyyymm.yyyymm],
               :include => [:fund], #ここでfundsテーブルをインクルード
               :order => "rank asc",
               :limit => 10
ビュー側 fund/ranking/index.rhtml
<%- if @pcipu1m.size > 0 -%>
<%- @pcipu1m.each_with_index do |rank, idx| -%>
    第<%= rank.rank %>位 #fund_rankingsのrank
    銘柄名:<%= rank.fund.name %> #fundsのname
<%- end -%>
<%- end -%>
まぁ、私みたいなror超初心者の参考のために(。・ω・。)





2011年8月24日水曜日

ruby on rails, cakephpなどlogが書かれない場合

今日、凄くはまりました、自分はアホかと思った。

Railsを使って開発しますが、logファイルが作れない。
環境設定等もバッチリと思いますけどなぜ?!!

結局、logディレクトリのmodでした、書き込み権限がないんだ!

今度何かログが書かれないことがあったら、まずこいう順番で調べようと思った

1.設定は問題ないか。environment.rbなど、ログレベルとか
2.ログ出力先のディレクトリの有無、なければ作る、そして書き込み権限、開発機なら777にしておこう、念のため tmpも777にしましょう
3.複数システム存在している場合、ちゃんと意図したものを見ているかどうかを確認

全部当たり前のことだけど、私はハマっちゃったToT

2011年8月21日日曜日

多次元のScripting.Dictionary構造

Sub testData()
    Dim shops As New Scripting.Dictionary
    
    '店を三軒追加します
    shops.Add "東京本店", New Scripting.Dictionary
    shops.Add "小金井店", New Scripting.Dictionary
    shops.Add "新宿店", New Scripting.Dictionary
    
    '東京本店に商品コードPD001~003を追加、定義したclsProductを利用
    shops.Item("東京本店").Add "PD001", New clsProduct
    shops.Item("東京本店").Add "PD002", New clsProduct
    shops.Item("東京本店").Add "PD003", New clsProduct
    
    'PD001~003の商品詳細を定義
    shops.Item("東京本店").Item("PD001").Name = "北海度牛乳"
    shops.Item("東京本店").Item("PD001").Price = 165
    shops.Item("東京本店").Item("PD001").Desc = "北海道のおいしい原乳"
    
    shops.Item("東京本店").Item("PD002").Name = "刺身の盛り合わせ"
    shops.Item("東京本店").Item("PD002").Price = 1200
    shops.Item("東京本店").Item("PD002").Desc = "新鮮だ新鮮だ"
    
    shops.Item("東京本店").Item("PD003").Name = "ハンドソープ"
    shops.Item("東京本店").Item("PD003").Price = 350
    shops.Item("東京本店").Item("PD003").Desc = "綺麗な手"
    
    '小金井店も同じ
    shops.Item("小金井店").Add "PD001", New clsProduct
    shops.Item("小金井店").Add "PD002", New clsProduct
    
    shops.Item("小金井店").Item("PD001").Name = "トーマス揺々セット"
    shops.Item("小金井店").Item("PD001").Price = 3200
    shops.Item("小金井店").Item("PD001").Desc = "子供大人気"
    
    shops.Item("小金井店").Item("PD002").Name = "果物ゼリ"
    shops.Item("小金井店").Item("PD002").Price = 200
    shops.Item("小金井店").Item("PD002").Desc = "りんご、ぶどう、いちご"
    
    Dim shop As Variant
    Dim product As Variant
    
    '全ての店から,店名を取得してループ
    For Each shop In shops.Keys
        'その店から,商品コードを取得してループ
        For Each product In shops.Item(shop).Keys
            '店名、商品コード、商品名、値段、改行、商品説明をコンソールに出力
            Debug.Print shop & " - (" & product & ")" & _
                        shops.Item(shop).Item(product).Name & " \ " & _
                        shops.Item(shop).Item(product).Price & vbNewLine & _
                        shops.Item(shop).Item(product).Desc
        Next
    Next
End Sub
こっちはclsProductの中身
Private mPdtName As String
Private mPdtPrice As Long
Private mPdtDesc As String

Public Property Let Name(ByVal newPdtName As String)
    mPdtName = newPdtName
End Property
Public Property Get Name() As String
    Name = mPdtName
End Property

Public Property Let Desc(ByVal newPdtDesc As String)
    mPdtDesc = newPdtDesc
End Property
Public Property Get Desc() As String
    Desc = mPdtDesc
End Property

Public Property Let Price(ByVal newPdtPrice As Long)
    mPdtPrice = newPdtPrice
End Property
Public Property Get Price() As Long
    Price = mPdtPrice
End Property

イミディエイトの出力はこんな感じ、新宿店は商品一つも登録しなかったので、
表示されませんでした。

東京本店 - (PD001)北海度牛乳 \ 165
北海道のおいしい原乳
東京本店 - (PD002)刺身の盛り合わせ \ 1200
新鮮だ新鮮だ
東京本店 - (PD003)ハンドソープ \ 350
綺麗な手
小金井店 - (PD001)トーマス揺々セット \ 3200
子供大人気
小金井店 - (PD002)果物ゼリ \ 200
りんご、ぶどう、いちご


データ構造はこうなっています

2011年8月10日水曜日

3秒後、ジャンプのmetaタグ

<META HTTP-EQUIV="Refresh" CONTENT="3;URL=http://newdomain.com/index.html">

2011年8月3日水曜日

mysqlのpassword変更

OSコンソールで

# mysqladmin -u user -h localhost password "newpw"


mysqlコンソールで

mysql> SET PASSWORD FOR 'user'@'%' = PASSWORD('newpw');