ツイッターでフォロワー増やすために自己リツイートを自動化してみた。
ツイッターでフォロワー増やすために自己リツイートを自動化してみた。
lambda使い始めるといろいろ楽しくて、自宅サーバーのこと忘れちゃいそうになる
PythonでTwitter APIを使う方法をまとめました。
プログラム部分よりTwittr API申請部分の方が大変だと思います。
awsのaws gateway + lambdaで指定urlからmetaタグ抜き出してjsonで返すAPI作成
それを使って、このブログでもブログの紹介カードが貼れるようになった
9月から新しいサイトを立ててやってたけど、やっぱり技術がらみでいろいろ垂れ流したいのでこのブログ復活することにしました。
urlで貼り付けた時にFacebookやTwitterはこのあたりのタグを見ておしゃれに貼り付けてくれる
<header> <!-- header内のタグの抜粋-->
<link rel="icon" href="/images/logo.png"> <!-- ブラウザで開いた時のアイコン-->
<meta name="description" content="世の中には..." /> <!-- 記事の説明(記事の最初のxx文字) -->
<meta name="keywords" content="ブログ,初めての○○シリーズ," /> <!-- キーワードリスト -->
<meta name="twitter:card" content="summary_large_image" /> <!-- Twitterに貼り付けた時の見た目-->
<meta name="twitter:site" content="@heisakusaku" /> <!-- Twitterアカウント -->
<meta property="og:url" content="https://enjoyall.comichi.com/blog_setup/" /> <!-- FB向け記事のURL -->
<meta property="og:site" content="enjoyall" /> <!-- FB向けサイト名 -->
<meta property="og:title" content="初めてのレンタルサーバーでのブログ・ホームページ開設 | enjoyall" /> <!-- FB向け記事タイトル-->
<meta property="og:description" content="世の中には.." /> <!-- FB向け記事の説明 -->
<meta property="og:image" content="https://enjoyall.comichi.com/images/mori.jpeg" > <!-- FB向け記事写真-->
<meta property="twitter:image" content="https://enjoyall.comichi.com/images/mori.jpeg" ><!-- Twitter向け記事写真 -->
</header>
subprocess module使って外部コマンド起動する時にオプションを区切って入れるのが面倒
以下↓↓↓みたいなやり方で配列作成すると楽できる
>>> import shlex, subprocess
>>> commandline = input()
ffmpeg -f image2 -r 10 -i %3d.png -r:v 10 -crf 18 -an -s:v 640x368 -pix_fmt yuv420p -vcodec libx264 invisible.mp4
>>> args = shlex.split(commandline)
>>> args
['ffmpeg', '-f', 'image2', '-r', '10', '-i', '%3d.png', '-r:v', '10', '-crf', '18', '-an', '-s:v', '640x368', '-pix_fmt', 'yuv420p', '-vcodec', 'libx264', 'invisible.mp4']
>>> exit()
今、このサイトは自作の静的サイト生成(static site generator)スクリプト(Ruby)で作ってたのですが、いろいろ改善しようと思ってる間にオープンソースで便利そうなのが出てきてしまったので、一旦そちらで新サイト開始します。
新しいサイト↓↓プログラミングのことも少しは書く予定
利用したStatic Site Generator
いろいろ調べた結果、ICS (Internet Connection Sharing)というのを止めた。
後で何か影響が出た場合のため、ここにメモ。(colinuxとかshareしてる気がする。。調べるの面倒)
changelogを書いているときに簡単に折り畳んでタイトルだけ並べられるように.vimrcいじった
vimrc changelog関連部分
autocmd BufRead *.chg setf changelog
autocmd FileType changelog set foldexpr=ChgLogFoldLevel(v:lnum) foldmethod=expr foldlevel=0
let g:changelog_username ="hassy"
function! ChgLogFoldLevel(lnum)
let l1 = getline(a:lnum)
if l1 =~"^\\t\\*[^*]"
return '>1'
elseif l1 =~"^\\t"
return 1
else
return 0
endif
endfunction
これでだいぶ読みやすくなった
RubyのRSS::MakerでRSS1.0生成すると、content:encodedが自動的にhtml_escapeされてしまい、CDATAとして埋め込んでくれないので、モンキーパッチングしてみた。
rss_cdata.rb
require 'rss'
module RSS
module BaseModel
def install_cdata_element(tag_name, uri, occurs, name=nil, type=nil, disp_name=nil)
name ||= tag_name
disp_name ||= name
self::ELEMENTS << name
add_need_initialize_variable(name)
install_model(tag_name, uri, occurs, name)
def_corresponded_attr_writer name, type, disp_name
convert_attr_reader name
install_element(name) do |n, elem_name|
<<-EOC
if @#{n}
rv = "\#{indent}<#{elem_name}>"
value = "<![CDATA[" + eval("@#{n}") + "]]>"
if need_convert
rv << convert(value)
else
rv << value
end
rv << "</#{elem_name}>"
rv
else
''
end
EOC
end
end
end
module ContentModel
def self.append_features(klass)
super
klass.install_must_call_validator(CONTENT_PREFIX, CONTENT_URI)
%w(encoded).each do |name|
klass.install_cdata_element(name, CONTENT_URI, "?", "#{CONTENT_PREFIX}_#{name}")
end
end
end
class RDF
class Item; include ContentModel; end
end
end
試してみる
require 'rss'
require './rss_cdata'
rss = RSS::Maker.make("1.0") do | maker |
maker.channel.about = "http://hoge.fuga/index.rdf"
maker.channel.title = "harahoro"
maker.channel.description = "hirehare"
maker.channel.link = "http://hoge.fuga/"
item = maker.items.new_item
item.link = "http://hoge.fuga/piyo.html"
item.title = "aheaheuhiha"
item.content_encoded = "<p>aheuhihaaa</p>"
item.dc_date = Time.now()
end
puts rss.to_s
結果
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:image="http://web.resource.org/rss/1.0/modules/image/"
xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
xmlns="http://purl.org/rss/1.0/">
<channel rdf:about="http://hoge.fuga/index.rdf">
<title>harahoro</title>
<link>http://hoge.fuga/</link>
<description>hirehare</description>
<items>
<rdf:Seq>
<rdf:li resource="http://hoge.fuga/piyo.html"/>
</rdf:Seq>
</items>
<taxo:topics>
<rdf:Bag/>
</taxo:topics>
</channel>
<item rdf:about="http://hoge.fuga/piyo.html">
<title>aheaheuhiha</title>
<link>http://hoge.fuga/piyo.html</link>
<content:encoded><![CDATA[<p>aheuhihaaa</p>]]></content:encoded>
<dc:date>2009-12-02T13:14:24+09:00</dc:date>
<taxo:topics>
<rdf:Bag/>
</taxo:topics>
<content:encoded><![CDATA[<p>aheuhihaaa</p>]]></content:encoded>
</item>
</rdf:RDF>
どうよ。
以下を”.vimrc”に追記
map ,t <ESC>:tabnew<CR>
map ,h <ESC>:tabp<CR>
map ,l <ESC>:tabn<CR>
これで、タブ移動、タブ作成が楽になる
いろいろな処理をするファイルをプラグインとして適当なディレクトリに入れておくと、それらをロードしてオブジェクト化するやりかた。
バッチ処理とかでカスタムな方法をインプリしたいときとかに使えるかと思う。
plugin_loader.rb
class PluginLoader
attr_reader :plugins
def initialize(plugin_base, extension = 'rb')
@plugin_base = plugin_base
@plugins = []
Dir.glob(@plugin_base + "*.#{extension}").each do |p|
require p
@plugins << Object.const_get(to_classname(p)).new
end
end
private
def to_classname(str)
str.sub(/^#{@plugin_base}/){""}.sub(/\.rb$/){""}.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
end
end
使い方はこんな感じ(あらかじめpluginsディレクトリにxxxx.rbファイルを作っておく)
test.rb
require './plugin_loader'
pl = PluginLoader.new(File.dirname(__FILE__) + "/plugins/")
pl.plugins.each do | p |
p.run
end
Rubyで動的に関数定義3
で書いた方法をつかって、PerlのTest::Baseっぽいのを書いてみる。
(Ruby Test::Baseってのがすでにあるみたいだけどね。)
まずは、test_base.rb
require 'test/unit'
class TestBase < Test::Unit::TestCase
@@test_template = {}
def run(*args)
return if@method_name.to_s == "default_test"
super
end
def self.start_test
self.parse if(@@test_template.empty?)
self.generate_tests
end
private
def self.parse
test_name = ""
buf = ""
buf_mode = ""
while line = DATA.gets do
line.chomp!
if(line =~ /^(===|---)/)
if(buf != "" && test_name != "" && buf_mode != "")
@@test_template[test_name][buf_mode] = eval(buf)
buf = ""
end
if(line =~ /^=== (.*)$/)
test_name = $1
@@test_template[test_name] = {}
elsif(line =~ /--- input (.*)$/)
@@test_template[test_name][:method_name] = $1
buf_mode = :input
elsif(line = ~/--- expected/)
buf_mode= :expected
end
else
buf += line
end
end
if(buf != "" && test_name != "" && buf_mode != "")
@@test_template[test_name][buf_mode] = eval(buf)
buf = ""
end
end
def self.generate_tests
@@test_template.each do |test_name,test_args|
define_method(test_name) do
result=__send__(test_args[:method_name],test_args[:input])
assert_equal test_args[:expected], result, " error on #{test_name}"
end
end
end
end
DATAの処理のところが、ちょっと(かなり?)スパゲッティーだけど、generate_testsの所でテスト用の関数をDATA内容に合わせて作成してる。
Test::Unit::TestCaseのrunメソッドで”default_test”を無視するようにして、TestCaseがテスト未定義時に勝手にdefault_testを実行するのを防いでる。(この部分を抜くとどうなるか試せば言ってる意味がわかるはず)
実際のテストのほうは、こんな感じで書く。
require './test_base'
require './testee'
class TestBaseTest < TestBase
def setup #setupとかは通常のTestCaseと同じ
@testee = Testee.new
end
def login_test(login_name) # DATAを利用するテストはtest_以外のメソッド名
@testee.login(login_name)
@testee.who_am_i?
end
def test_without_data # DATAを使わないテストはtest_で始まるメソッド名
true
end
end
TestBaseTest.start_test #最後にstart_testでテストを生成しておく
__END__ #ここからテストに渡すパラメータ
=== test_should_login_by_hoge
--- input login_test #inputの後ろに利用するメソッド名
:hoge
--- expected
:hoge
=== test_should_login_by_fuga
--- input login_test
:fuga
--- expected
:fuga
inputの後ろのメソッド名が一個しかかけなかったり、フィルタとか便利なものがなかったり、”ruby Test::Base”よりかなりはしょってるけど、1ファイルで出来てるのでその辺はしょうがないと割り切る。
じゃあの。
有名人との飲み会は初めてなのでちょっと緊張したけど、アルコールと羽生さんの毒舌っぷり(?)のせいで最終的にはべろんべろんの飲み会になってしまった。
飲みながら書いたメモ(いわゆる腰リールなんだけど、リールが壊れたのでただのメモ帳。。)を発表してみます。
もっといろいろ話したけど、書いちゃいけないこともありそうなので、この辺で。
いやぁ、いい刺激になった。
<
強化学習によって学習させたニューラルネットワークを使ったハムレット(4目並べ)ゲームを作った。
だいぶ前からニューラルネットワークとか人工知能とかに興味があったんだけど、なかなかプログラミングする暇がなくてほったらかしにしてた。
そのうち、内容を解説していくつもり。
今回は、そのさわりの部分。
アーキテクチャは、ざっくりこんな感じ。
+-----------------+
+-------->lRL Agent |
| | |
| +---->|[Value Function] |
| | +-------------+---+
| | |
State | | Reward | Action
| | |
| | +-----------+ |
| +---|Environment|<--+
| | |
+-------| |
+-----------+
動きとしては、
言葉にすると、現在のStateの価値は、次のステートの価値+rewardに近づくように学習されるということ
で、RL Agentが持つ価値関数[Value Function]の部分はどのような関数になるのかは未知であるので、ニューラルネットワークでState -> Valueの対応付けを学習させることにした。
参考書籍:
<iframe id=”4627826613”src=”http://motivation.drivendevelopment.jp/amazon_query_proxy/queryproxy_ruby.cgi?ItemId=4627826613” onload=”fitFrame(this.id)” frameborder=”0” width=”100%”></iframe>
2003年にこんなサイト作ってた。時代がやっと追いついた?
複雑系・人工知能ゲーム
こまった。xslt内でawsのクエリーをつなげるということをしていたのだが、今回の認証系の変更により全滅。
xslt内でHMAC-SHAの変換って出来んのかなぁ?
まいった
Perlでバイナリファイルをいじる場合にいろいろと同じ問題に遭遇するので、忘れないようにメモ。
読み込む場合に”getc”使うと、ファイルが終わってないのに終了してしまうことがある。
正しくは”read”を使う。
my $filename = $ARGV[0];
open my $file,'<',$filename or die;
binmode $file;
my $val;
while(read($file, $val, 1)){
}
これで1byteづつ処理できる。実際はバイナリの構造にあわせてreadするバイト数を変える。
バイナリを数値として処理するためには、その構造にあわせてunpackする。
unpack("C",$val); #unsigned byte
unpack("S",$val); #unsigned short
unpack("L",$val); #unsigned long
unpack("c",$val); #signed byte
unpack("s",$val); #signed short
unpack("l",$val); #signed long
bit処理の場合は、いろいろ問題がある。
ビット反転”~”は、ビット長にあわせてpackしてから処理する。
~pack("c",$i); # $iは数値。一旦byteにしてからビット反転
ビットの”&(and),|(or),^(xor)”は、両方同じビット長にする。
もしくはunpackしてから処理する(unpackしても同じビット長(環境依存)になるからね)
pack("s",$j) ^ pack("s",$i); # $i,jは数値。両方shortにしている
unpack("s",$val) ^ $i; # $valは読んだバイナリ,$iは数値。
ビットシフト”«”, “»“は、数値化(unpack)してからじゃないと動かない。。。(何故?)
unpack("S",$i) << 1
と、いうことで、実は「ビット反転」以外はunpackして処理する。ということ。
例として、μ-lawとPCMの変換(なんのこっちゃ?という人はwavファイルの勉強を。。)
my $mantissa = unpack("C",~$val); #$valが読み込んだバイナリ
my $sign = (unpack("C",$val) < (0x0080))? -1:1;
my $exponent = ($mantissa >> 4) & (0x0007);
my $segment = $exponent + 1;
$mantissa = $mantissa & (0x000F);
my $step = (0x0004) << $segment;
my $g191_value = pack("S",$sign * (((0x0080) << $exponent) + $step*$mantissa + $step/2 - 4*33));
#最後に"S"でpackしてunsigned shortに
書き出したい構造にあわせてpackしてやる。
wavファイルのヘッダとかだとこうなる。
my $form = "";
$form .= "RIFF";
$form .= pack("L",$size + 36); #data size + headersize(-8)
$form .= "WAVE";
$form .= "fmt ";
$form .= pack("L",16); #fmt chunk size
$form .= pack("S",1); # pcm
$form .= pack("S",1); # mono
$form .= pack("L",8000); # 8k sampling
$form .= pack("L",16000); # Byte/sec = sampling * 2byte(16bit 量子化) * 1(mono)
$form .= pack("S",2); # Byte/sample(8bit量子化) * channel(mono)
$form .= pack("S",16); # 8bit量子化
$form .= "data";
$form .= pack("L",$size); #data size
signedとunsignedを変換するにはpackしてunpackというややこしい方法が必要。
my $i = -100;
my $unsigned_value = unpack("C",pack("c",$i));
wav関連でもぞもぞしてるのバレバレですね。
ルータの冗長化の方式としてVRRPとHSRP(Cisco only)がある。
これは、通常「マスター側ルータ」がarp応答するのに対し、マスターダウン時には「スタンバイ側ルータ」がarp応答するようになって対応するというもの。
で、これにNATを組み合わせて下図のように組もうとすると、問題が起こった。
+-----------+ +-----+ 192.168.1.251 +-------+ 192.168.10.251
|my server |-----|L2 SW|------------------|Master |-----
|192.168.1.1| | | Virtual Router +-------+
+-----------+ | | (192.168.1.254)
| | +-------+
| |------------------|Standby|-----
+-----+ 192.168.1.250 +-------+ 192.168.10.250
NAT変換:
192.168.1.1 <=> 192.168.10.1
VRRPの場合の設定(f0が外側)
Router1(config)# track 1 interface f0 line-protocol
Router1(config)# int f1
Router1(config-if)#vrrp 1 ip 192.168.1.254
Router1(config-if)#vrrp 1 priority 150
Router1(config-if)#vrrp 1 track 1 decrement 100
Router1(config-if)#ip nat inside
Router1(config)# int f0
Router1(config-if)#ip nat outside
Router2(config)# int f1
Router2(config-if)#vrrp 1 ip 192.168.1.254
Router2(config-if)#ip nat inside
Router2(config)# int f0
Router2(config-if)#ip nat outside
Router1/2共通(config)# ip nat inside source static 192.168.1.1 192.168.10.1
問題は、Standby側のルータがNAT設定したIPのarpに応答してしまい、duplicate addressとなってしまう問題。
HSRPでは、NATのredundancyオプションを利用して回避できる。(NATのredundancyオプションにstandbyで設定した名前を指定する)
HSRPの場合の設定(f0が外側)
Router1(config)# track 1 interface f0 line-protocol
Router1(config)# int f1
Router1(config-if)#standby 1 ip 192.168.1.254
Router1(config-if)#standby 1 priority 150
Router1(config-if)#standby 1 track 1 decrement 100
Router1(config-if)#standby 1 preempt
Router1(config-if)#standby 1 name hsrp1
Router1(config-if)#ip nat inside
Router1(config)# int f0
Router1(config-if)#ip nat outside
Router2(config)# int f1
Router2(config-if)#standby 1 ip 192.168.1.254
Router2(config-if)#standby 1 preempt
Router2(config-if)#standby 1 name hsrp1
Router2(config-if)#ip nat inside
Router2(config)# int f0
Router2(config-if)#ip nat outside
Router1/2共通(config)# ip nat inside source static 192.168.1.1 192.168.10.1 redundancy hsrp1
VRRPでも、descriptionを設定してredundancyやればできるはずなんだけど、できなかった。
久々のネットワークねたでした。
drivendevelopment.jp を driven-development.jpに変えた。
また、検索にひっかからなくなるな。
あと、コメント欄(はてなブックマーク)も空になっちゃう。
追記 ~~~
ドメイン元に戻した。
理由: ハイフンないのが流行みたい。
Railsである特定のmodelの検索(find)時に必ずsortをかけたいというような場合には、modelのfindをカスタマイズするのが便利。
class Hoge < ActiveRecord::Base
class << self
alias_method :find_org, :find
def find(*params)
options = {:order => "fuga desc"}
options.update(params.last.is_a?(::Hash)? params.pop : {})
find_org(*params.push(options))
end
end
end
もとのfind(find_org)を呼び出すときに、paramsを’*‘でもとに戻すの忘れてえらい目にあった。
railsで使えるidiomを見つけた。
rubyで、あるメソッドの呼び出しが以下のようになっている場合、
hoge(:param, :option1 => true , :option2 => false)
以下のやり方でオプション部分だけを取り出せる
def hoge(*prams)
options = params.last.is_a?(::Hash)? params.pop : {}
pp options
pp params
end
参考:
ActiveSupport::CoreExtensions::Array::ExtractOptions#extract_options!
ActiveRecord::Errors関係をいろいろいじりたいと思って、まずは、ActiveRecord::Validationをかじってみた。
Validationの流れの参考にでもなれば。
最終的に、save/save!を契機にvalidation関連が呼ばれる。
だいたいそんな感じっぽい
参考:
またでたよ。IE。
jasonpとかでスクリプトを読み込んで実行するときに、最初のkicker(loader?)的なスクリプトを書く場所によってエラーが発生する。
「インターネットサイトxxxを開けません。操作は中断されました」というエラーウィンドウがでて、サイトは表示されない状態となる。
例:
kicker.js
function kicker(){
var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.setAttribute("src","./callee.js");
document.body.appendChild(script);
return true;
}
scriptタグを作ってcallee.jsを読み込むだけ。
callee.js
function callee(){
document.getElementById("hogefuga").appendChild(document.createTextNode("hogefuga"));
return true;
}
callee();
テキストノードを埋め込むだけ。最後に自分を呼んでいる。
buggy.html(動かないケース)
<html>
<head>
<script type="text/javascript" src="./kicker.js" charset="utf-8" ></script>
</head>
<body>
<div>
<div id="hogefuga"></div><!-- ここにテキストノードが書き加わる -->
<script>
<!--
kicker();
//-->
</script>
</div>
</body>
</html>
問題は、scriptタグがdivに囲まれていることらしい。
下記のように変更すると動く
:
<div>
<div id="hogefuga"></div>
</div>
<script>
<!--
kicker();
//-->
</script>
:
でも、いつもいつも外側に書けるわけでもないよね?
そういう時はeventListenerだそうだ。
if(window.addEventListener){
window.addEventListener("load",kicker, false);
}else{
window.attachEvent("onload",kicker);
}
もう、いい加減面倒くさいよ。
参考: http://yusuke.homeip.net/diary/2006/03/12/1142155862799.html
ちなみに、何を作っていて気付いたかというと、このブログの「コメント」欄。
といっても、「はてなブックマーク」をコメント欄代わりに表示しているだけ。
<iframe id=”4894712873”src=”http://motivation.drivendevelopment.jp/amazon_query_proxy/queryproxy_ruby.cgi?ItemId=4894712873” onload=”fitFrame(this.id)” frameborder=”0” width=”100%”></iframe>
今読んでる。
ところどころややこしい言い回し(日本語のせい?)があるものの、じっくり読めば筆者の言おうとしている「伝わるコーディング」がわかってくる。
Javaならではの問題も多いけど、思想的にはプログラマーは知っていて損はなと思う。
スクリプト言語やってるとすぐにハッシュで引数とか渡しがちだけど、筆者の言うように、それにより伝わりにくいコードになるのは確かだ。
でも、それをやらないと面倒くさいコーディングが増えるのも確かだ。
そのあたりのビミョーなところも読みながら自分なりに結論を出すのだろう。。。
javascriptによる簡易regexでは対応できないケースがでてしまったので、いろいろ参考にしつつruby版を作った。
require 'resolv'
require 'pp'
class MailAddressValidator
def self.validate(address)
return validate_by_regex(address) && validate_by_MX(address)
end
def self.validate_by_regex(address)
addr_spec = %r{^(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+))*)|(?:"(?:\\[^\r\n]|[^\\"])*")))\@(?:(?:(?:(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+)(?:\.(?:[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+))*)|(?:\[(?:\\\S|[\x21-\x5a\x5e-\x7e])*\])))$}
address =~addr_spec
end
def self.validate_by_MX(address)
mxdomain = address[/[^@]+$/]
Resolv::DNS.new.getresource(mxdomain,Resolv::DNS::Resource::IN::MX) rescue nil
end
private_class_method :validate_by_regex, :validate_by_MX
end
使うときはこんな感じ
require File.dirname(__FILE__) + '/mail_address_validator'
print (MailAddressValidator.validate('hogefuga@hogefugadennnenn.naiyo')) 'ok':'ng' #=> ng
これをつかって、同期Ajaxでチェックしてる。
日本語が変だな。。。要は javascriptでxmlhttprequest.open(‘GET’,”xxxxxx”, false)という形で同期的にチェックしてる。
参考:
http://blog.livedoor.jp/dankogai/archives/51189905.html
http://www.ruby-lang.org/ja/man/html/resolv.html
追記 2009-04-13:
spellミスを直しました。id:Uchimataさんありがとうございます。
はてなブックマークがはじめてコメント欄として機能した記念すべき日です。
Railsを使わないで、rubyからActionMailerでメールを送信したくなったので、やり方のメモ。
ActionMailerは、gemでインストール済みと仮定。
Sakuraレンタルサーバ(さくら)の場合、”POP before SMTP”なので、送信前にpop認証が必要となります。
require 'rubygems'
require 'action_mailer'
require 'net/pop'
class MyMailer < ActionMailer::Base
alias_method :base_perform_delivery_smtp, :perform_delivery_smtp
@@pop3_auth_done = nil
def self.setup_for_sakura
self.delivery_method = :smtp
self.smtp_settings = {
:address => 'xxx.sakura.ne.jp',
:port => 587,
:domain => 'xxx.sakura.ne.jp',
:pop3_auth => {
:server => 'xxx.sakura.ne.jp',
:user_name => 'hoge@xxx.sakura.ne.jp',
:password => 'passw0rd',
:expires => 1.hour,
:authentication => :login
}
}
self.template_root = File.dirname(__FILE__) + "/templates"
self.perform_deliveries = true
end
def mail_contents(user,contents)
from "hoge <hoge@xxx.sakura.ne.jp>"
recipients "#{user} <#{user}>"
subject "日本語タイトルほげふが"
body :user => user, :contents => contents
end
private
def perform_delivery_smtp(mail)
do_pop_auth if !@@pop3_auth_done or (Time.now - smtp_settings[:pop3_auth][:expires]) >= @@pop3_auth_done
base_perform_delivery_smtp(mail)
end
def do_pop_auth
pop = Net::POP3.new(smtp_settings[:pop3_auth][:server])
pop.start(smtp_settings[:pop3_auth][:user_name], smtp_settings[:pop3_auth][:password])
@@pop3_auth_done = Time.now
pop.finish
end
end
で、./templates/my_mailer/mail_contents.erbに、テンプレートを適当に作成。
<%= @user %> 様
<%= @contents[:hello] %>ですねん。
ほな
これを利用する側はこんな感じ。
require 'rubygems'
require File.dirname(__FILE__) + "/my_mailer"
MyMailer.setup_for_sakura
MyMailer.deliver_mail_report('user@hogefuga.com', {:hello => "こんにちは"})
rubygemsへのパスが通ってない場合は、$LOAD_PATH.push(“パス”), ENV[‘GEM_HOME’] = “パス”、でライブラリ及びGEM_HOMEのパスを通しておきましょう。
参考: http://railsforum.com/viewtopic.php?pid=47672
またしてもIE。
ラジオボタンを動的に生成する場合、デフォルトとか以前の結果とかをチェックした状態で表示するために
var myRadio = document.createElement('input');
myRadio.type = 'radio';
myRadio.value = 'hoge';
myRadio.checked = true;
とかやるじゃないですか。
IEの場合、これではチェックが付かない。
ドキュメントにappendした後に変更する必要があるんだって。
いい加減にしてくれよIE
javascriptでformをname属性でアクセスする手法は良く使う。
var abc = document.formname.hoge.value;
これを、動的に生成させたformで行おうと思った場合、IEで問題が起こる。
var myNode = document.getElementById('fuga');
var myForm = document.createElement('form');
myForm.name = 'formname';
var myInput = document.createElement('input');
myInput.name = 'hoge';
myInput.type = 'text';
myInput.size = "40";
myForm.appendChild(myInput);
myNode.appendChild(myForm);
dom生成時に.nameでname属性を変更しているにもかかわらず、IEでは独自のIDがつけられてしまい、上記のname属性を利用したアクセス方法ではアクセスできないのだ!
有り得ないよ。
そこで、こんなユーティリティ関数が必要になる。
function createNamedElement(tag,name){
var isIE =/*@cc_on!@*/false;
var element;
if (name) {
element = (isIE)? document.createElement('<' + tag + ' name="' + name + '">'): document.createElement(tag);
element.name = name;
} else {
element = document.createElement(tag);
}
return element;
}
IE恐るべし。
ちなみに’cc_on’の所は、IEの判定で良く使われる方法(らしい)。
この記事のタグ名’bug_or_spec’のネーミングセンスの良さに自画自賛
以下の方法では動かない。
package hoge;
sub new{
my $class=shift;
my $self={'msg2' => 'harahoro','hoge' => \&hoge};
bless $self,$class;
return $self;
}
sub fuga{
my $self=shift;
my $msg =shift;
my $classname=ref $self;
print "from $classname : hello! $msg\n";
}
sub hoge{
my $self=shift;
my $msg = shift;
print "I am calling fuga\n";
$self->fuga("hoge : $msg and ". $self->{"msg2"});
}
1;
package main;
my $moga=hoge->new;
$moga->{'hoge'}->('self hash');
当然、以下も動かない。
package hoge;
sub new{
my $class=shift;
my $self={'msg2' => 'harahoro'};
bless $self,$class;
$self->init;
return $self;
}
sub init{
my $self=shift;
$self->{"hoge"} = \&hoge;
}
sub fuga{
my $self=shift;
my $msg =shift;
my $classname=ref $self;
print "from $classname : hello! $msg\n";
}
sub hoge{
my $self=shift;
my $msg = shift;
print "I am calling fuga\n";
$self->fuga("hoge : $msg and ". $self->{"msg2"});
}
1;
package main;
my $moga=hoge->new;
$moga->{'hoge'}->('self hash');
以下の2点が問題
なので、以下のような解決方法になる。
package hoge;
sub new{
my $class=shift;
my $self={'msg2' => 'harahoro'};
bless $self,$class;
$self->init;
return $self;
}
sub init{
my $self=shift;
$self->{"hoge"} = $self->hoge_invocant;
}
sub fuga{
my $self=shift;
my $msg =shift;
my $classname=ref $self;
print "from $classname : hello! $msg\n";
}
sub hoge_invocant{
my $invocant=shift;
return sub { hoge($invocant, @_);};
}
sub hoge{
my $self=shift;
my $msg = shift;
print "I am calling fuga\n";
$self->fuga("hoge : $msg and ". $self->{"msg2"});
}
1;
package main;
my $moga=hoge->new;
$moga->{'hoge'}->('self hash');
hoge_invocantが
「invocantをレキシカルクロージャとして保持しhogeをinvocantつきで呼び出す無名関数」
を返す。
ここで無名関数を使うべきだということに気付いた。
sub init{
my $self=shift;
$self->{"hoge"} = sub {hoge($self, @_);};
}
追記~~
<iframe id=”4873112036”src=”http://motivation.drivendevelopment.jp/amazon_query_proxy/queryproxy_ruby.cgi?ItemId=4873112036” onload=”fitFrame(this.id)” frameborder=”0” width=”100%”></iframe>
本屋で↑を立ち読みしたら(買え! >> 俺) 載ってた。
同じ結論になってたようなので、買わなくてもいいってことか?
~~追記終わり
こんなのをlibに入れて利用してる。
module YamlFixture
def record_to_yaml_fixture(rec_class_name)
eval(rec_class_name).find(:all).inject({}){|h, v| h.merge(v.attributes["id"] => v.attributes)}.to_yaml
end
end
to_jsonのときはattributesを取り出してjson化してる。
to_yamlのときはオブジェクトそのものをyaml化してる。
なので、
@items.to_json
と
@items.attributes.to_yaml
が等価
ということかな。
Perlは、内部的に改行をLFとして扱い、入力時・出力時に環境に合わせたコードで出力する。
なので、Windows上のperl (Strawberry perl使用)で、以下のようにすると
perl -e 'print "\x0a";'
出力に 0x0d0a (CR+LF)がでてしまう。
Windows環境でもLFで出したい時もある。
そのときは、こうしなければならないみたい。
perl -e 'binmode STDOUT; print "\x0a";'
$/とか$\とかいろいろいじったけど、できなかった。
Rubyってハッシュスライスがないんだよね。
Perlで簡単に
@hash{@fields}=@values;
とかできることができない。。
かなりつらいんですけど。。
hashの一部をupdateする場合のやり方はこんな感じらしい。
hash.update(Hash[*keys.zip(vals).flatten])
%APPDATA%\Subversion\serversにある。
XP/2000だと、
c:\Document and Settings\ユーザ名\Application Data\Subversion\servers
Vistaだと、
c:\Users\ユーザ名\AppData\Roaming\Subversion\servers
このファイルで
[global]
http-proxy-host=xxxxx.xxx.xxx
http-proxy-port=8080
とか設定する
英語キーボードで日本語入力するときいちいち
左Alt + ~ (チルダ)
とかめんどくさいので、変更した。(AXキーボードのドライバを使うパターンで)
regedit
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters
LayerDriver JPN : REG_SZ : kbdax2.dll
OverrideKeyboardIdentifier: REG_SZ : AX_105KEY
OverrideKeyboardSubtype: REG_DWORD : 0x00000001 (1)
OverrideKeyboardType: REG_DWORD : 0x00000007 (7)
あと、CAPS -> Ctrlへの変換も忘れないように書いておく
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Keyboard Layout
Scancode Map : REG_BINARY
0000 00 00 00 00 00 00 00 00
0008 02 00 00 00 1D 00 3A 00
0010 00 00 00 00
今のCtrlはCtrlのまま変更しない
PC買ったら必ずやる。
バッチファイルのアイコンとか、.jarのアイコンとかを変更する方法。(かなり前のメモ)
Javaのアプリケーションで利用される”.jar”ファイルは、Windowsではファイルの関連付けの機能でjavawに関連付けされ、全て同一のアイコンに設定されています。
バッチファイルも、同様に変な歯車のアイコンに設定されています。
これでは、アイコンがどのアプリケーションでも同じになってしまい、プロフェッショナルな感じがしません。
そこで、JScript (JavaScriptに似て非なるWindowsのスクリプト)を用いてアイコン付きのショートカットを作成する方法で解決します。
用意するもの。
上記を同一フォルダにおいてJScriptをダブルクリックで実行する形になります。
JScriptファイル内容(makeShortcut.js):
hello.batをhello.lnk/hello.icoと関連付けてデスクトップに作成する場合
Shell = new ActiveXObject("WScript.Shell");
DesktopPath = Shell.SpecialFolders("Desktop"); //デスクトップにショートカット作成
link = Shell.CreateShortcut(DesktopPath + "\\hello.lnk");
link.Arguments = ""; // .batファイルに引数を渡す場合ここに記述
link.Description = "hello.bat shortcut";
link.HotKey = "";
link.IconLocation = Shell.CurrentDirectory + "\\hello.ico";
link.TargetPath = Shell.CurrentDirectory + "\\hello.bat";
link.WindowStyle = 3;
link.WorkingDirectory = Shell.CurrentDirectory;
link.Save();
multipart/mixedのメールが複数分割されて送られてきました。メール本文は空っぽで、全て添付ファイルになっていました。
どうやら、outlook expressで送信した場合に起こる現象のようですが、こちらで読めないので困ってしまいます。
中身を見ると、テキストの本文に続き、
Content-Type: application/octet-stream;
Content-Transfer-Encoding: base64
となっていて、この部分以降に怪しげな文字列が延々と続いています。
この部分以降は、base64でエンコードされたバイナリ添付ファイルなわけです。
この部分を取り出してエンコードを解けば(デコードすれば)、添付されていたファイルを復活できるはずです。
で、perlの出番です。
Step1:base64部分だけのファイルを作る
> ls
xxx[1_3].dat
xxx[2_3].dat
xxx[3_3].dat
> cat *.dat > abc.dat
> vim abc.dat
#ここで、必要な部分(怪しげな文字列の部分)以外を削除
Step2: perlでデコード
Perlのソース
#!/usr/bin/perl -w
use MIME::Base64;
binmode STDOUT,'raw';
binmode STDIN,'raw';
while(<>){
print decode_base64($_);
}
楽勝だね。
Railsで試験をする時に、日付に依存する機能(次の誕生日までの日数を求めるとか。。)がある時、今までならfixtureに
date: <%= Date.today().to_s %>
とか、動的にfixtureを定義していたのですが、いろいろロジックが複雑になりだしたので、発想を逆にすることにしました。
つまり、テストの日付を固定するという方法です。
基本的に、Date.today()や、Time.now()を上書きしてやるのですが、他のテストに影響を与えないようにやる必要があります。
そこで、Test::Unit::TestCaseのsetup/teardown内で、関数の再定義、もとの定義への戻しをやってやります。
hoge_controller_test.rb
:
#このテストは2008年9月で試験
class Date
def self.fixed_today
return Date.new(2008,9,1)
end
end
class HogeControllerTest < Test::Unit::TestCase
def setup
Date.instance_eval do
alias :orig_today :today
alias :today :fixed_today
end
end
def teardown
Date.instance_eval do
alias :fixed_today :today
alias :today :orig_today
end
end
:
end
特異メソッドのaliasを作成するので、instance_evalを利用してaliasによる関数の入れ替えをしています。
あいかわらず、初歩的なところにいます。。。(-_-;)
perlのCGIでアクセス解析のためにリファラ(訪れた人が前に見ていたページ)を取ろうとしてたのですが、検索サイトによって文字が化けたりしてたので、utf8に統一してみようということで、以下のようにしました。
<script language="JavaScript">
<!--
document.write('<img src="http://hoge.fuga.funya/access.cgi?rr=' + escape(document.referrer) + '" />');
// -->
</script>
imgタグ内でアクセス解析用のcgiを呼んでいます。cgi側でHTTP_REFERERを取ると、このスクリプトを入れたページ自身になるので、パラメータとしてrrにリファラを入れています。
#!/usr/bin/perl -w
use strict;
use CGI;
use Encode;
use Encode::Guess qw/euc-jp shiftjis 7bit-jis/;
use utf8;
my $file="access.log";
my $q=new CGI;
my $ref = url_decode($q->param('rr')); #前のページ
my $referer = url_decode($q->referer()); #見られてるページ
my $result="\"$ref\",\"$referer\"\n";
open(FILE,">>:encoding(utf8)", $file) or error($q, "can't open");
print(FILE $result);
close(FILE);
&printimg;
exit;
sub url_decode{
my $str = shift;
return 'hoge' unless $str;
$str =~ tr/+/ /;
$str =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
my $decoder = Encode::Guess->guess($str);
return $decoder->decode($str) if(ref($decoder));
return decode("utf8",$str);
}
sub printimg{
open(COUNTERIMG, "./counter.gif") or error($q, "can't open");
binmode(COUNTERIMG);
print "Content-type: image/gif\n\n";
print <COUNTERIMG>;
close(COUNTERIMG);
}
urlエンコードされた文字を一旦もどしてからEncode::Guessでデコードしてファイルに書き込んでいます。
これにより、文字コードが統一されます。
urlエンコードをデコードするときにpackを利用しているのでutf8フラグ関係が心配なので、utf8フラグをつける前にurlデコードしています。
最後にimgを転送して終了。
なんか美しくないけど、動く。
さて、我が愛機のVaioですが、リカバリソフトが入っている領域として「EISA」というのがあるのですが、これを消すことができなくて困ってました。
リカバリディスクを作成した後は不要となるのですが、これを消すには作成したディスクからOSの再インストールというのが常套手段のようでした。
僕は、そういうことを知らずに山ほどソフトを入れたので、いまさらインストールしなおしは勘弁して欲しいと思っていたのですが、ようやく解決方法がわかりました。
となります。
僕の場合、colinuxが数ギガあったので、colinuxフォルダごとマウントしたドライブに入れ替えました。
(別ドライブとすることもできますが、マウントしてオリジナルフォルダごとコピーするほうがcolinuxを丸ごと移動できてよかった。)
言語によっていろいろ違うなぁと実感。
Perl
use Encode;
binmode STDOUT, ":encoding(shiftjis)";
my @str = qw(00110000 01000010);
my $final = join('',map{pack('B8',$_)} @str);
$final = decode('UTF-16BE',$final);
print $final;
Perlのmap関数の使い勝手は最強ですね。
java
import java.io.*;
public class BinaryDecode{
public static void main(String[] args) {
String[] strArray = {"00110000","01000010"};
byte[] bytes = new byte[2];
int i = 0;
for(String s : strArray){
int j = Integer.parseInt(s,2);
if(j > 127){ j = j - 256;} //-128~127に収める処理
bytes[i++] = (byte)j;
}
try{
System.out.println(new String(bytes,"UTF-16BE"));
}catch(IOException e){
e.printStackTrace();
}
}
}
javaの場合、文字列が可変長の場合、”byte[]”の代わりに”List
いずれ、こういうコマンドも必要になるんだろう。
netsh interface ipv6 show prefixpolicy
知っておく。
ipv6 install
も忘れないようにしなきゃ
マウスで選択したURLに飛ぶブックマークレット。
ttpで始まるものにも飛べるように改造してもいいかもしれない。
javascript:(function()%20%7Bvar%20w='';if(window.getSelection)%7Bw=window.getSelection();w=''+w;%7Delse%20if(document.selection)%7Bw=document.selection.createRange().text;%7Dif(w.length%3E0)%7Bwindow.open(w);%7Delse%7Balert(%22nothing%20selected%22);%7D%7D)()
R(recency:最新購買日) いつ買ったか、最近購入しているか
F(frequency:累計購買回数) どのくらいの頻度で買っているか
M(monetary:累計購買金額) いくら使っているか
http://www.atmarkit.co.jp/aig/04biz/rfm.html
便利なワンライナー
grep -r -l xxxxx . | xargs perl -pi.bak -e "s/xxxxx/yyyyy/g"
xxxxxの含まれているファイルを抽出して、中身のxxxxxをyyyyyに書き換え。
バックアップファイルとして.bakを作成
すぐ忘れるのでメモ。
>xxxx & #バックグラウンドで実行
>jobs #バックグラウンドで動いてるやつをリストアップ
[1] - xxxx
>fg 1 #jobsで出た番号のやつをフォアグラウンドにもってくる
>[ctrl-z] #フォアグラウンドのやつをサスペンド
>bg #フォアグラウンドのやつをバックグラウンドに持っていく
Rubyで動的に関数定義
Rubyで動的に関数定義2
からの続き。
で、今回いろいろ調べていた大元の理由である「テストケースの自動生成」だけど、こんな感じで使えそう。
テスト対象
class Testee
def login(login_user)
@login_user ||=login_user
end
def who_am_i?
@login_user
end
end
一つのテストケース内でログインの試験を複数回やると、初回のログイン情報が残るためにfailする。
require 'test/unit'
require 'testee'
class TesteeTest < Test::Unit::TestCase
def test_should_login
@testee.login(:hoge)
assert_equal :hoge, @testee.who_am_i? # => ok
@testee.login(:fuga)
assert_equal :fuga, @testee.who_am_i? #=> fail :hogeが残ってる
end
end
今までなら、複数の試験を手書きしてた。
そこで、今回勉強してきた、define_methodを利用してテストケースを自動生成してみる。
require 'test/unit'
require 'testee'
class TesteeTest < Test::Unit::TestCase
def self.generate_test
while login_name = DATA.gets do
login_name.chomp!
define_method("test_should_login_by_#{login_name}") do
@testee.login(login_name)
assert_equal login_name, @testee.who_am_i? , " error on login by #{login_name}"
end
end
end
def setup
@testee = Testee.new
end
end
__END__
:hoge
:fuga
うまくやれば、PerlのTest::Baseくらい使い勝手が良くなるかもね。
web Rubyで動的に関数定義
からの続き。
生成後のインスタンスに関数を動的に生やす場合は、いろいろ試したが、以下の方法が一番よさそう。
インスタンス変数、クラスインスタンス変数、ローカル変数(クロージャ)が利用できる。
class Dog
@dog_counter = 0
def initialize(name)
self.class.class_eval { @dog_counter += 1 }
@dog_name = name
end
def perform
puts "*****"
puts "I am #{@dog_name}." # instance variable @
puts "Total Dogs are #{self.class.class_eval {@dog_counter}}." # class instance variable @
puts "bow!"
end
end
dog_hoge = Dog.new('hoge')
dog_hoge.perform
dog_fuga = Dog.new('fuga')
dog_fuga.perform
インスタンスdog_fugaにだけ関数をオーバライドしてやる。
instance_eval, define_methodを利用することにより、外部ローカル変数を利用できる。
lexical_local_variable = 'Wooooo!'
(class << dog_fuga;self;end).instance_eval do
define_method(:perform) do
puts "*****"
puts "I am #{@dog_name}." # instance variable @
puts "I am one of the #{self.class.class_eval {@dog_counter}} Dogs." # class instance variable @
puts "#{lexical_local_variable}" # lexical closure(local variable)
end
end
dog_hoge.perform
dog_fuga.perform
いろいろ使えそうだ。
追記
Rubyで動的に関数定義3(for Test::Unit)
会社の重鎮に教えてもらった。
man xxx | col -bl > xxx.txt
こうすると、下線とかboldとかが取れてきれいなテキストで落とせる。
FizzBuzzってはやってたけど、3の倍数と3の付く数字でアホになる場合はどうなるかやってみた。
perl -e'print+(aho)[$_%3 and (/3/)?0:1]||$_,$/for 1..100'
もっと短くなるのだろうか。。。
参考:
FizzBuzz - Golf Challenge
追記: 3項演算子いらないみたい。
perl -e'print+(aho)[$_%3 and !/3/]||$_,$/for 1..100'
レポート用のクエリーとかで、日付を月初にあわせてグループ化したかったりする。
sqlでは以下のようにすればできる。
select cast(date_format(date_column,'%Y-%m-01') as Date) from table
group by cast(date_format(date_column, '%Y-%m-01') as Date);
本当にcastが必要なのかが良くわからん。
module_eval(= class_eval),instance_evalがある。
なんで、この機能を調べているかというと、Railsで試験しているときに、ログインユーザを切り替えようと、一つのテスト関数内でログインを繰り返してたら、同じテスト関数内は同一セッションになって「すでにログインしてます」とかなったわけさ。(俺のインプリでは)
で、いちいちログアウトさせるのも面倒なので、いっそのことテスト関数を自動生成しようと思った。
そのうち詳しく書こうと思うので[todo]タグ。
追記:
module_eval(=class_eval)は、レシーバのクラスにインスタンス関数を定義。
irb> class Hoge
irb> end
irb> hoge = Hoge.new
irb> Hoge.module_eval {def fuga() p 'fuga';end}
irb> Hoge.fuga #=> error
irb> hoge.fuga #=> 'fuga'
irb> Hoge.new.fuga #=> 'fuga'
instance_evalは、レシーバがクラスの場合、クラス関数を定義(def self.xxxってやるやつと同等)
irb> class Hoge
irb> end
irb> hoge = Hoge.new
irb> Hoge.instance_eval {def fuga() p 'fuga';end}
irb> Hoge.fuga #=> 'fuga'
irb> hoge.fuga #=> error
irb> Hoge.new.fuga #=> error
instance_evalは、レシーバがobjectのインスタンス場合、そのobjectのインスタンス関数を定義
irb> class Hoge
irb> end
irb> hoge = Hoge.new
irb> hoge.instance_eval {def fuga() p 'fuga';end}
irb> Hoge.fuga #=> error
irb> hoge.fuga #=> 'fuga'
irb> Hoge.new.fuga #=> error
これに変数のスコープとからむとさらにややこしそうだ。
そのうち調べよう。ということでまだ[todo]
マインドマップはlifehackツールの一つとしてとても面白いと思う。
だけど、マインドマップをソフトウェアで描くのはどうもしっくり来ない。
どう見てもただの「ツリー作成」ソフトにしか見えない。
WBS(Work Breakdown Structure)作成にマインドマップ使えと勧める記事
とかいうのを見ると余計にそう思う。
対象の探し方
find ./-name "*.xsl" | xargs grep -l amazon | xargs grep -L AWSE
ほっときすぎていろいろなサイトで問題が出ているのが発覚
railsでto_yamlでactiverecordのオブジェクトをyaml化すると、日付関連がこのようになった。
mydate: !timestamp 08/10/10
で、これをrubyのYAML::loadで、読ませると’argument out of range’というエラーになる。
日付で問題なのはなぜか10月(他にもあるかもしれない。)
irb> require 'yaml'
irb> YAML::load("mydate: !timestamp 08/10/10")
ArgumentError: argument out of range
irb> YAML::load("mydate: !timestamp 08/11/10")
=> {"mydate"=>Thu Jan 10 00:00:00 UTC 2008}
(あれ?、よくみると11月も1月になってるし。。。)
irbでDateをyaml化すると、以下のようなフォーマットになる。
irb> Date.new(2008,10,10).to_yaml
=> "--- 2008-10-10\n"
なので、きっとrailsがto_yamlで変なことをしてるんだろう。
いろいろ調べて、environment.rbの記述を変更することで対処できた。
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.update :default => "%Y/%m/%d"
なぜか、’%y’で設定してたので、’%Y’に変えた。
俺のミスってことだな。
Rubyにはクラスにもインスタンス変数を作成することができる。
class Hoge
def self.count_instance
@num = 0 if @num.nil? #クラスのインスタンス変数
@num += 1
end
def self.get_count
@num
end
def initialize(num)
self.class.count_instance
@num = num
self
end
def get_count
@num
end
end
これがあるんならクラス変数(@@)とかっていらないのかな?
テンプレート内に日本語を書くと文字化けする。
utf-8がTemplateで読まれるときのフラグの関係だと思われる。
いろいろ調べてTemplate::Provider::Encodingという、かの有名なmiyagawaさんのモジュールを使えば良いことがわかった。
Index: Chariot.pm
===================================================================
--- Chariot.pm (revision 13330)
+++ Chariot.pm (working copy)
@@ -7,6 +7,7 @@
use YAML;
use App::Chariot::Config;
use Template;
+use Template::Provider::Encoding;
use File::Spec;
use XML::RSS;
use Scalar::Util;
@@ -55,9 +56,11 @@
my $self = shift;
Template->new(
{
+ LOAD_TEMPLATES => [ Template::Provider::Encoding -> new({
INCLUDE_PATH =>
File::Spec->catfile( $self->config->assets_dir, 'tmpl' ),
ABSOLUTE => 1,
+ })]
}
);
}
実は、このサイトがずっと英語メニューだったのはこのためだったのだ。:-p
crossreview(クロスレビュー) || レビューで繋がる、みんなの輪 » hassylin
に参加した。
主にプログラミング関連の本をレビュー予定。
読むのが遅いので、dankogaiさんのように速攻レビューというようには行かないけど。
参考にしてもらえれば幸い。
本当なら自分で作りたかった。
書くの忘れてた。
autocmd BufRead *.chg setf changelog
これを付け加えておくと、拡張子.chgのものは全てvimでchangelogとして扱われる。
<0.5> expected but was
<0.5>.
意味不明
調べてみると、floatの誤差の問題だった。
irb > 0.05 + 0.05 + 0.05 + 0.05 + 0.05 + 0.02 + 0.02 + 0.02 + 0.02 + 0.02 + 0.15 == 0.5
false
困った。全部100倍して計算するのか。。。あほくさ
assert_in_deltaというのがあるのでこれを利用することにした。
こういう風に分けると意外とうまくいく気がする。
このブログではコメントとかが入らないので反応が見れないのが残念。(はてぶとかに載ればいいけどね。)
どんな言語でもそうだと思うけど、日付のアップデート時には、月→日の順番でアップデートする。
先に日をアップデートすると、31日の処理にバグが出る。
たまには振り返っておく。
form_forを使いつつpartialレンダリングするには、以下の方法でpartial側
formにform_forのブロックパラメータを渡す必要がある。
例: ‘:locals => {:f => f}’のところ。
<h1><%= _('Create a New Account') %></h1>
<% form_for :user, @user, :url =>{:action => 'signup'} do |f| -%>
<%= render :partial => 'signup_form', :locals => {:f => f} %>
<%= submit_tag _('Sign up') %>
<% end -%>
タグ別アーカイブに対応した。(但し、複数タグの絞込みはできない。)
複数タグでの絞り込みは、オンラインアーキテクチャじゃないと厳しそうなので。。
package App::Chariot::C::TagIndex;
use Moose;
with 'App::Chariot::Role::C';
sub create {
my ($self, $c) = @_;
my $ifile = File::Spec->catfile($c->config->assets_dir, 'tmpl', 'tagindex.tt');
my %tags = ();
for my $entry (@{$c->dat->list}) {
for my $item (reverse @{$entry->items->list}) {
for my $t (@{$item->tags}){
$tags{$t} = [] unless $tags{$t};
unshift(@{$tags{$t}},$item);
}
}
}
for my $t (keys %tags){
my $cnt =1;
my @list = @{$tags{$t}};
my $ofile = File::Spec->catfile($c->config->output_dir, "$t.html");
$c->render(
$ifile => $ofile, {
tag => "[$t]",
items => [@list],
},
);
}
}
1;
App::Chariotのコントローラ群にApp::Chariot::C::TagIndexというモジュールを追加するやり方にした。
きっと、もっと「モダン」なやり方があるのだろうけど、とりあえずこれで対処。
$A(document.getElementsByName(element_name)).each(function(elm){
if(elm.checked){
ほげほげ;
}
});
でおけ。
あとは、css等をいじる必要がある。
super_preとpreが同じ処理になっているので、(&")等を変換するように改変
すごくいい。
[http://motivation.drivendevelopment.jp/images/mvpen.jpg:image]
Module::Installで作ったモジュールには通常incディレクトリとMANIFEST等が
入るが、svnで管理する場合にははずすことが多い。
Module::Installが利用できる環境でperl Makefile.PLすればよい。
その後、
make manifest
make dist
等する。
PathTools-3.2501を使う必要がある。
Version指定するときは、CPANのダウンロードリンクのid/以下を使う
my @result = grep{$_} @array;
tokuhiromさんのApp::Chariotという簡易ブログツールを入れた。
モダンなPerlということで、かなりすっきりしたソースでわかりやすい。
これから勉強。とりあえず、以下の変更をした。
-*pでプライベートとなるようにData::Clmemo::Itemを改変
-タイトルにPerlモジュール名(::)が入っても処理できるようにData::Clmemo::Itemを改変
Index: Item.pm
===================================================================
--- Item.pm (revision 13612)
+++ Item.pm (working copy)
@@ -8,7 +8,7 @@
sub parse {
my ($class, @lines) = @_;
- my ($title, $tag, $body) = (shift @lines) =~ /\*(.*?)(\[.*\])?:(.*)/;
+ my ($title, $tag, $body) = (shift @lines) =~ /\*([^p][^[]*)(\[.*\])?:(.*)/;
return unless $title;
$title =~ s/(^\s*|\s*$)//g;
perldoc perldelta
で読む。
再帰的な関数を無名で扱うためのアルゴリズム。
rubyの例:
Y= proc{|g|
proc{|f|
g[f[f]]
}[
proc{|f|
g[proc{|y| f[f][y]}]
}
]
}
fact = proc {|f| proc{|n| n==0 ? 1: n * f[n-1]}}
p Y[fact][5] #=> 120
解説希望。 よくわかりません。
複数パッケージを含む以下のようなperlスクリプトで(&)プロトタイプ宣言した関数を実行すると、動きません。(Can’t call method ‘fuga’ without a package or object….)
package hoge;
use base 'Exporter';
our @EXPORT = qw/ fuga foo/;
sub fuga(&){ print $_[0]->();}
sub foo(){ print $_[0];}
1;
package main;
import hoge;
# 駄目パターン
fuga {'fuga'};
#プロトタイプ宣言(&)してないやつはOK
foo('foo');
#関数として渡すとOK
fuga(sub{'fuga'});
プロトタイプで’&’を指定した場合、subをつけない無名関数(ブロック)を渡せるはずですが、渡せません。
で、package hogeを別ファイルに置くと、動きます。
use 'hoge'
fuga {'fuga'}; #OK
なんか変だなぁ。
importとuseは違うのかなぁ?
なんか間違ってる?
eventの標準機能を止めないと思わぬことがおこる。
_disable_default_event: function(evt){
if (evt.preventDefault) {
evt.preventDefault();
} else {
evt.returnValue = false;
}
};
この関数をイベント処理後に呼び出す。
idea: Directorは、以下の基本creatorを組み合わせる
build_element(type, attr={});
build_elements(function, params = []);
where function(v,i) -> [type, attr[]]
params.map.function.map.function(v,i){bild_element.apply(null.v);};
func.apply(null, array)とするとarrayが展開される。
Vista対応されたらVaio に入れる。
日々のメモ用
changelogは拡張子が無いので、ファイルのダブルクリックではエディタ(gvim)が開かない。
なので、dosのバッチファイルを書く。
でも、gvim起動後にもdos窓が開きっぱなしになってしまう。
以下のやり方で開かなくできる。
"START コマンド名"
*タイトル[タグ]:ボディー
という形式
‘*p’とするとプライベート
vimでは、+oで追加できる。
let g:changelog_username = "hassy"
としてユーザ名を指定する。(.vimrc)