serverspecをグループ分けして実行する方法

serverspecは、デフォルトの設定だとhost毎にspecファイルを書かなければいけません。

spec
├── spec_helper.rb
└── example.com
    └── httpd_spec.rb

そのため、同じミドルウェアがインストールされている場合、同じソースを書かなければいけないのが少し面倒くさいです。

spec
├── spec_helper.rb
├── example.com
│   └── httpd_spec.rb // 同じspecファイル
└── example2.com
    └── httpd_spec.rb // 同じspecファイル

これを解決する方法が公式に書いてありました。

http://serverspec.org/advanced_tips.html

グループ分けしてspecファイルを管理する

app、base、dbなど役割に応じてディレクトリを作成して、specファイルを分けます。

spec
├── app
│   └── ruby_spec.rb
├── base
│   └── users_and_groups_spec.rb
├── db
│   └── mysql_spec.rb
├── proxy
│   └── nginx_spec.rb
└── spec_helper.rb

Rakefileを修正

Rakefileに、host毎のテストケースを先ほどのディレクトリ単位で指定します。(複数組み合わせることも可能)

require 'rake'
require 'rspec/core/rake_task'

##### いじるのは、ここから #####
hosts = [
  {
    :name  => 'proxy001.example.jp',
    :roles => %w( base proxy ),
  },
  {
    :name  => 'proxy002.example.jp',
    :roles => %w( base proxy ),
  },
  {
    :name  => 'app001.example.jp',
    :roles => %w( base app ),
  },
  {
    :name  => 'app002.example.jp',
    :roles => %w( base app ),
  },
  {
    :name  => 'db001.example.jp',
    :roles => %w( base db ),
  },
  {
    :name  => 'db002.example.jp',
    :roles => %w( base db ),
  },
]
##### ここまで #####

hosts = hosts.map do |host|
  {
    :name       => host[:name],
    :short_name => host[:name].split('.')[0],
    :roles      => host[:roles],
  }
end

desc "Run serverspec to all hosts"
task :spec => 'serverspec:all'

class ServerspecTask < RSpec::Core::RakeTask

  attr_accessor :target

  def spec_command
    cmd = super
    "env TARGET_HOST=#{target} #{cmd}"
  end

end

namespace :serverspec do
  task :all => hosts.map {|h| 'serverspec:' + h[:short_name] }
  hosts.each do |host|
    desc "Run serverspec to #{host[:name]}"
    ServerspecTask.new(host[:short_name].to_sym) do |t|
      t.target = host[:name]
      t.pattern = 'spec/{' + host[:roles].join(',') + '}/*_spec.rb'
    end
  end
end

spec_helper.rbを修正

spec_helper.rbを下記の内容に書き換えます。

require 'serverspec'
require 'net/ssh'

include Serverspec::Helper::Ssh
include Serverspec::Helper::DetectOS

RSpec.configure do |c|
  c.host  = ENV['TARGET_HOST']
  options = Net::SSH::Config.for(c.host)
  user    = options[:user] || Etc.getlogin
  c.ssh   = Net::SSH.start(c.host, user, options)
  c.os    = backend.check_os
end

実行してみる

全部のホストを実行
$ bundle exec rake serverspec:all 
ホストを指定して実行

Rakeファイルに記入したhost名の最初の「.(ドット)」までがprefixとなります。

$ bundle exec rake serverspec:proxy001
$ bundle exec rake serverspec:app001

Rakefileに直接書くのが嫌な人は

YAMLにhostを書いて、管理したりする方法もあるそうです。

【css】MediaQueryを使ってみた

PCとスマホのページを1ソースで作るために、ウィンドウの幅に応じてスタイルを変更する、css3のMediaQueryを使ってみました。

@media screen and (max-width: 640px) {
    body {
        background-color: red;
    }
}

MediaQueryを使用する時は、Mediaを明示的に指定しないといけません。

なので、上のcssは、Mediaがscreenなおかつウィンドウ幅が640px以下の場合に適用されます。

複数条件の指定などもできるみたいなので、いろいろ応用ができそう。

cssが適用される優先順位

たまに混乱してしまうのでまとめます。

  • idはclassより強い
  • 階層が深いほうが強い
  • styleを直接書くのが一番強い

idはclassより強い

この場合は、idの方が強いので背景色は赤色になります。

<div id="hoge" class="hoge"></div>
#hoge {
    background-color: red;
}
.hoge {
    background-color: green;
}

階層が深いほうが強い

この場合、階層の深いほうが強いので、後から.hogeの背景色を変えたとしても、.fugaの子階層にある.hogeの背景色は変わりません。

<div class="fuga"><div class="hoge"></div></div>
<div class="hoge"></div>
.fuga .hoge {
    background-color: red;    
}
.hoge {
    background-color: green;
}

styleを直接書くのが一番強い

たとえidで背景色を指定していても、要素に直接styleが書かれていた場合は、その値が適用されます。
この場合は、背景は緑色になります。

<div id="hoge" style="background-color: green;"></div>
#hoge {
    background-color: red;
}

シェルスクリプトでif文を書く

すごく基礎的なことなんですが、毎回ググっているので自戒の念を込めて書きます。

if [ "hoge" == "hoge" ]; then
  echo true
else 
  echo false
fi

重要なのは[]の中は半角スペースを必ず開けること。

if ["hoge" == "hoge"]; then
  echo true
else 
  echo false
fi

これはエラーになる。毎回忘れる。
なんでエラーになるかを解説したとてもわかりやすい記事があったような記憶があるのですが、全く思い出せない。
誰か知ってたら教えて下さい。

facebookの評判をチェックできるサイトを作りました

http://fb-checker.tanihiro.com/

f:id:w6500:20140123233729p:plain

f:id:w6500:20140123234451p:plain

どんなサイトか

URLを入力して、そのURLのいいね数の内訳(share, like, comment)の数を表示します。

なおかつ、facebook上で公開範囲が全体になっている投稿からURLをキーワードにして検索をし、投稿を表示します。

作ろうと思ったきっかけ

FQLでなにか面白い値取れないかと調べていたら、URLのいいね数の内訳が取ってこれたので、それを調べられるツールを作ろうと思い立ったのがきっかけです。

それだけでは面白くないので、SearchAPIも使って投稿を取得し、評判をチェックできるようにしちゃおうと。

学生時代以降全く触っていなかったFireWorksを使って、自分でデザインもしました。(久々すぎて全然使い方わからなくなっていた)

まとめ

これを使えば、自分のサイトがFacebook上でどれだけ話題になっているかをほんのり知ることができるので、ぜひ使ってみてください。

【objective-c】UIWebViewでローカルにあるHTMLを表示する

xcode内にHTMLを格納して、そのHTMLをWebViewで表示する方法です。

// UIWebViewの初期化
UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
// htmlのパスの取得(今回はsample.html)
NSString *path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"html"];
// ファイルの読み込み
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]];
[self.view addSubview:webView];

日付期間の重複チェック

開始日時と終了日時を持っているデータがあって、その期間と重複しているデータがないかチェックするときの条件式のメモです。

  • start_date(開始日)
  • end_date (終了日)
start_date <= {対象終了日付} AND end_date >= {対象開始日付}