KotlinのInt.timesがムカついたので拡張関数作った。

KotlinにもInt.timesがあって簡単にループできるんだけど、こいつカウンターがない…。
IntelliJからメソッドジャンプしてみたら、以下のようになっていた。

package kotlin

public inline fun Int.times(body : () -> Unit) {
    var count = this;
    while (count > 0) {
       body()
       count--
    }
}

うん、まぁわかる。わかるけれどカウンター付けてよ!
ということで、自分で作った。拡張関数は便利すなぁ…。

public inline fun Int.times(body : (index:Int) -> Unit) {
    var index = 0
    while (index < this) {
        body(index)
        index++
    }
}

使い方はこうです。

10.times { index ->
    println(index)
}

こっちを採用してほしいですね。


パーフェクトRubyを読んだら俺Rubyのことわかってなかったなと…

結婚式のときにとちさんからお祝いで頂いていたパーフェクトRubyですが、パラパラとめくりながら時々読んでいたのですが、ちゃんと読んでみようと思って読んでみると、俺Rubyのことわかってなかったと痛感した。

特に、Enumerableのところでした。配列とハッシュは頻繁に使うのですが、each, map, inject, find, selectとかをよく使っていたのですが、さらに色々便利なメソッドがあるのだなー…。便利じゃないか?と思ったメソッド群はこちら。

array = [2,2,3,4,4,5]
array.select {|n| n.even? } # => [2, 2, 4, 4]
array.reject {|n| n.even? } # => [3, 5]

逆もできたんだな!と(まぁ条件を逆にすればいいだけではあるけど)。

%w(Alice Bob Charlie).grep(/a/i) # => ["Alice", "Charlie"]
["a", "b", 1, 2].grep(String) # => ["a", "b"]

今までselect内で正規表現チェックしていた気がする。

array = ["a", "b", "c", "d", "e"]
array.take(3) # => ["a", "b", "c"]
array.drop(3) # => ["d", "e"]

array.slice(0..2)ってやってた。まぁどっちでもできるんだけれど。
dropはいいですね。

array = [1, 2, 3, 4, 5]
array.take_while {|n| n < 3 } # => [1, 2]
array.drop_while {|n| n < 3 } # => [3, 4, 5]

今のところあんまり使う機会はなさそうだけれど。

array = [1, 2, 3, 1.0, 2.0, 3.0, "a", "b", "c"]
array.group_by {|v| v.class } # => {Fixnum=>[1, 2, 3], Float=>[1.0, 2.0, 3.0], String=>["a", "b", "c"]}

これはコードレビューで見たことあった。使ったことはない。

array = [1, 2, 3, 4, 5]
array.partition {|n| n.even? } # => [[2, 4],[1, 3, 5]]

selectとrejectを同時にできるのはいいなと思った。

array = [1, 2, 3, 4, 5]
array.min # => 1
array.max # => 5
array.minmax # => [1, 5]

minとmaxは知っていたけれど、minmaxは知らなかった!

array = ["a", "bb", "ccc"]
array.min_by {|n| n.length } # => "a"
array.max_by {|n| n.length } # => "ccc"
array.minmax_by {|n| n.length } # => ["a", "ccc"]

min_byとかあったんだなー…。

パーフェクトRubyは、正直俺はまだまだRubyとRailsの上辺だけを使っていたのだなと考えさせられる本でした。もっとRubyを使いこなせるようになりたい!と思ったので、Rubyもっと書きます。Rakeとかもっとちゃんと活用したい。gemを自分で書いていきたい。

パーフェクトRuby

パーフェクトRuby
著者:Rubyサポーターズ
価格:3,456円(税込、送料込)
楽天ブックスで詳細を見る


Deviseで不要な機能、ルーティングをオフにする

Okayama.rbでとあるプロジェクトをしているのですが、その最初のほうを自分が作り込むから待っててくれといって早数週間。めっちゃDeviseでハマってました…。
rails-apiを使って、jsonを返すだけのapiサーバーを作ろうとしているので、deviseでのログインはトークンからだけでいい。
なので、config/routes.rbでdevise_forを使わないでもいいだろうと思ってコメントアウトしたらテストが死んでしまったので調査開始。

また、グループウェア的なのを作ろうとしているのだけれど、だれでも登録できるグループウェアだとダメなので、登録機能をオフにするのもどうすればいいんだろう?と思っていたら、自分でオンにしているだけだった…。まず登録機能をオフにするには:registerableをコメントアウトすればいい。

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable,
         # :registerable,
         :recoverable,
         :trackable,
         :validatable,
         :token_authenticatable
end

これでregistration系のルーティングは消せます。

次に、ログイン(サインイン)用のルーティングを消します。
これはルーティング側に書きました。skip: [:sessions]らしいです。
また、Deviseのルーティングは普通のusersを使ってしまうとユーザー管理のコントローラと被ってしまうので、敢えてこれを変更しておきました。それがpath: :meの部分です。

devise_for :users, path: :me, skip: [:sessions]
resources :users, except: [:new, :edit]

これによって設定されたルーティングはこうなりました。

     user_password POST   /me/password(.:format)      devise/passwords#create
 new_user_password GET    /me/password/new(.:format)  devise/passwords#new
edit_user_password GET    /me/password/edit(.:format) devise/passwords#edit
                   PATCH  /me/password(.:format)      devise/passwords#update
                   PUT    /me/password(.:format)      devise/passwords#update
             users GET    /users(.:format)            users#index
                   POST   /users(.:format)            users#create
              user GET    /users/:id(.:format)        users#show
                   PATCH  /users/:id(.:format)        users#update
                   PUT    /users/:id(.:format)        users#update
                   DELETE /users/:id(.:format)        users#destroy

パスワード更新用のルーティングと普通のユーザー管理用のルーティングのみ残すことに成功。やったね!


cssで自動的にカウントアップする

list-styleで括弧付の数字を振りたいときという記事を見まして、まさにこれがやりたかったわけですが、応用もできるよ、ということで、h2タグを使った例が紹介されていました。

h2 { counter-increment : chapter ; }
h2:before { content : "第" counter(chapter) "条" ; }

これって俺の好きなdl, dt, ddで使えるやん!と思った次第です。
なんでこれを使いたくなったかというと、利用規約とかを整形している最中だったのですが、番号振るのが億劫だったのです。

以下、sassです。dtが出る度に自動で条を振ってくれます。括弧が必要だったら付ける程度で。
あと、dd要素内でol liの入れ子があったらよきに計らってくれます。
入れ子先で括弧付き番号を振ってくれます。便利。

dl {
  dt {
    font-weight: bold;
    counter-increment: chapter;
    &:before {
      content: "第" counter(chapter) "条("
    }
    &:after {
      content: ")"
    }
  }
  dd {
    margin: 0 0 1em 2em;
    &> ol > li {
      list-style: outside decimal;
      margin-left: 2em;
      &> ol > li {
        list-style-position: inside;
        counter-increment: cnt;
        &:before {
          display: marker;
          content: "(" counter(cnt) ") ";
        }
      }
    }
  }
}

cssは奥が深いですのう…。