yasuoza diary

web and life

checkout with updating tags

When writing middle - big application, tags is very useful to find method and variable definition. Especially for RoR application, ripper-tags is useful and it would be great if update tags when git checkout.

Here is the opt out solution.

1
2
touch .git/hooks/post-checkout
chmod +x .git/hooks/post-checkout

post-checkout will be

1
2
3
4
5
#!/bin/sh

if [[ -n $SKIP_TAG || $SKIP_TAG != 1 ]]; then
  ripper-tags -R --exclude='test' --exclude='spec' --exclude='vendor/bundle'
fi

If you don’t want to update tags when checkout, simply set SKIP_TAG environment variable to 1 like

1
SKIP_TAG=1 git checkout your_branch

Opt in

1
2
3
4
5
#!/bin/sh

if [[ -n $UPDATE_TAG && $UPDATE_TAG == 1 ]]; then
  ripper-tags -R --exclude='test' --exclude='spec' --exclude='vendor/bundle'
fi
1
UPDATE_TAG=1 git checkout your_branch

NeoBundleLazy ‘VimFiler’

To NeoBundleLazy VimFiler, NeoBundle supports explorer option.

1
2
3
4
5
6
7
8
9
NeoBundleLazy 'Shougo/vimfiler.vim', {
\   'depends' : 'Shougo/unite.vim',
\   'autoload' : {
\       'commands' : ['VimFiler', 'VimFilerCurrentDir',
\                     'VimFilerBufferDir', 'VimFilerSplit',
\                     'VimFilerExplorer', 'VimFilerDouble'],
\       'explorer' : 1
\   }
\ }

This works with following option!

1
let g:vimfiler_as_default_explorer = 1

Wow!heart_eyes

How do you indent ruby’s if..else assignment?

There are several ways to write if...else variable assignment.

1
2
3
4
5
@products = if params[:category]
              Category.find(params[:product]).products
            else
              Products.all
            end
1
2
3
4
5
@products = if params[:category]
  Category.find(params[:product]).products
else
  Products.all
end
1
2
3
4
5
@products = if params[:category]
    Category.find(params[:product]).products
  else
    Products.all
  end
1
2
3
4
5
6
@products =
  if params[:category]
    Category.find(params[:product]).products
  else
    Products.all
  end

Which one do you prefer?

I prefer last one. Because this can keep horizontal length much smaller and vim-ruby’s auto indent also supports this syntax.

FYI: http://stackoverflow.com/questions/8745299/recommended-indentation-style-for-ruby-if-blocks-that-assign-a-value-to-a-vari http://stackoverflow.com/questions/2925028/how-do-you-assign-a-variable-with-the-result-of-a-if-else-block

2014年前半を振り返って

2014年も前半が終わった。2014年になっていろんなイベントもあり、 働き始めた頃とはだいぶ考え方が変わったことも多かった。

まず、スキルの話。ここで言うスキルは技術力、課題・問題を解決、回避出来る能力と自分は定義している。 これまではバックエンドからフロントエンドまですべてを予め網羅しようと考えて勉強してきた。 ただ、最近はすべてを前もって網羅しておく必要はなく、必要になったらその時に勉強すればいいやと思うようになった。 勉強はもともと好きだから、苦じゃないんだけど、これまでは知らないことに恐怖を感じていた事が多く、何かに追われて 勉強していた気がする。 これからはそうではなく、わからなかったことは今勉強できるという考えでスキルを伸ばして行ければと思う。

次に時間の話。タイム・イズ・マネー、この言葉はすべてを表していると思った。これまではそこまで時間を意識することは なかったけど、これからは時間を大事にしたい。

最後にお金の話。お金は大事だと考えるようになった。 お金のためだけに働くのはたぶん無理だけど、やっぱり、お金が無いのは困る。 自分の中での優先順位でもお金はだいぶ低かったんだけど、この半年、具体的には結婚してからはお金の優先順位が上がった。 自分の中の優先順位、何が自分にとって幸せなのかは、これからもたまに考えたい。

これから30歳まではスケールするお金の稼ぎ方を慌てず考えていきたいなーなんて思った。

疲れやすいから、年末まで程よく一生懸命生きたい。

octpress rake new_post wrapper command

Save following content as new-post.

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
29
30
#!/usr/bin/env bash

function create () {
  local title=$@
  rake new_post["$title"]
}

function usage() {
  echo "USAGE"
  echo "    new-post 'This is my new post'"
}


if [[ -z $1 ]]; then
  usage
  exit 1
fi

while [ "$1" != "" ]; do
      arg=$1
    case "$arg" in
        -h | --help ) usage
                      exit
                      ;;
        * )           create ${arg[@]}
                      exit
                      ;;
    esac
    shift
done

With above command, you can start writing new post via

1
$ new-post 'This is my super entry'

sunglassessunglassessunglasses

Support tmux with “reattach-to-user-namespace” to work in multi OS

When using tmux with ‘reattach-to-user-namespace’ to enable clipboard copy paste support in OSX, you may have ~/.tmux.conf

1
set-option -g default-command "reattach-to-user-namespace -l zsh"

However with this configuration, tmux will fails on another platforms such as linux when reattach-to-user-namespace not installed.

So, your have at least 2 option to prevent it.

  • Prepare another ~/.tmux.conf.
  • Detect OS and use another default-command for each OS.

First option is easy but dull. Who wants to write same content but very last line?

Second option seems not to be easy, but IS easy. You can do like:

Detect OS pattern

~/.tmux.conf

1
if-shell 'test "$(uname -s)" = Darwin' 'set-option -g default-command "exec reattach-to-user-namespace -l zsh"'

Detect OS and load os specific configuration file pattern

~/.tmux.conf

1
if-shell 'test "$(uname -s)" = Darwin' 'source-file $HOME/.tmux-osx.conf'

and ~/.tmux-osx.conf

1
set-option -g default-command 'exec reattach-to-user-namespace -l zsh'

That’s it!

Read more:

ChrisJohnsen/tmux-MacOSX-pasteboard/Usage.md

remove_const vs stub_const

If you’re writing test with rspec, sometime you want to CHANGE constants like

1
2
3
4
5
6
7
8
9
10
11
# foo.rb
class Foo
  BAR = 'bar'
end

# foo_spec.rb
describe Foo do
  it 'have constant BAR' do
    expect(Foo.BAR).to be '???'
  end
end

You can choose many ways to change constants.

remove_const

First options is to use Module#remove_const.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# foo_spec.rb
describe Foo do
  before do
    @__orig_bar = Foo::BAR.dup
    Foo.send(:remove_const, :BAR)
    Foo::BAR = '???'
 end

 after do
    # restore to original constant.
    # without this, Foo::BAR remains '???'
    Foo.send(:remove_const, :BAR)
    Foo::BAR = @__orig_bar
 end

  it 'have constant BAR' do
    expect(Foo::BAR).to eq '???'
  end
end

The merit of this way is to change constants completely and the constant is evaluated directly. Adding to it, this method works without any libraries.
The demerit of this way is that this is something like META programming. This may not be easy to understand for ruby beginner.

stub_const

Second option is to use stub_const defined in rspec-mocks.

1
2
3
4
5
6
7
8
9
10
11
12
# foo_spec.rb
describe Foo do
  before do
    # no need to restore.
    # It restores after Foo example finished.
    stub_const('Foo::BAR', '???')
  end

  it 'have constant BAR' do
    expect(Foo::BAR).to eq '???'
  end
end

The merit of this way is easy to setup and easy to understand.
Ths demerit of this way is that stub_const depends on rspec-mocks, so if you want to use stub_const with minitest, you have to HACK minitest.

conslusion

Chosing remove_const vs stub_const depends on your situation. I think if the constant is important for buisiness logic, you should choose remove_const. If the constant is no so important testing and using rspec, you choose stub_const.
I think this discussion has no goal, but I think having many options is one of the the ways to be a HACKER.

Stub sharedManager with OCMock

If you are iOS/Mac developer, you may have written singleton like following convention:

1
2
3
4
5
6
7
8
9
static UserModelManager *sharedManager_ = nil;

+ (UserModelManager *)sharedManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedManager_ = [[UserModelManager alloc] init];
    });
    return sharedManager_;
}

If UserModelManager has secretKey instance method like:

1
2
3
4
- (NSString *)secretKey
{
    return "secret key provided from server side";
}

Then you can call secretkey method via

1
[[UserModelManager sharedManager] secretkey];

It’s OK until you have to stub secretKey in a test.

The solution to stub sharedManager and secretkey is:

1
2
3
_mockUserModelManager = [OCMockObject niceMockForClass:[UserModelManager class]];
[[[_mockUserModelManager stub] andReturn:@"test-key"] secretkey];
[[[[_mockUserModelManager stub] classMethod] andReturn:_mockUserModelManager] sharedManager];

To clean up your stub methods, DO NOT forget stopMocking in tearDown.

1
2
3
4
5
6
- (void)tearDown
{
  [super tearDown];

  [_mockUserModelManager stopMocking];
}

Multi GitHub pages with custom domain

I have two GitHub pages

each sites are hosted by GitHub pages using custom domain.

To use custom domain for GitHub pages, create CNAME file and write like:

1
www.yasuoza.com

With this file, you can see domain setting on Github repository > Settings > GitHub Pages like:

Next, open your DNS configure page, setup like:

Wait 1~3 hours(depend on you DNS server or environment).

Then open teminal and type like:

1
2
3
4
5
$ dig www.example.com +nostats +nocomments +nocmd
;www.example.com.                     IN      A
www.example.com.              3592    IN      CNAME   username.github.io.
username.github.io.           43192   IN      CNAME   github.map.fastly.net.
github.map.fastly.net.        22      IN      A       199.27.76.133

Tips

If you publish username.github.io repository to www.yoursite.com, then GitHub redirects username.github.io to www.yoursite.com.
However, if you publish another repository to subdomain.yoursite.com, GitHub does not redirect www.yoursite.com/another to subdomain.yoursite.com.
If you want to redirect www.yoursite.com/another to subdomain.yoursite.com, you should write redirect JavaScript like:

1
2
3
4
5
6
(function() {
   var GITHUB_PAGES_HOST = 'www.yoursite.com';
   if (document.location.host === GITHUB_PAGES_HOST) {
       document.location.href = document.location.href.replace(GITHUB_PAGES_HOST, '');
   }
}());

Then www.yoursite.com/another will be redirected to subdomain.yoursite.com.
Cheerssunglasses

人の信頼を失う方法

  • 経営陣の顔色ばかり気にする
  • 情報を公開/共有しない
  • 女性(特に若い女性)と男性で態度を変える