before_validation コールバック関数に引数を持たせる

やりたいこと

電話番号入力欄で後ろに半角、全角スペースがあった時に空白を取り除いてからvalidationを行いたい時に、before_validationを使って書きました。
電話番号だけじゃなくメール入力欄など他の場面でも利用できると思いmoduleを使って書いた時に詰まった部分があったのでどうすればいいか共有します。

とりあえずapp/models/user.rbに下記のように最初は書いていました。

app/models/user.rb
class User < ActiveRecord::Base
# ... 省略 ...

  before_validation :trim_space

  def trim_space
    self.phone.gsub!(/[ \p{blank}\r\t\n\f]/, "")
  end

end

gsub!なのですが!を使ってオブジェクトの状態を変更しておかないと返り値が全角、半角を取り除いた状態にならないので!を使うかもしくは下記のような書き方にしてみてください

app/models/user.rb
  self.phone = self.phone.gsub(/[ \p{blank}\r\t\n\f]/, "")
  return self.phone


これでまずは電話番号の入力欄だけは全角、半角を取り除けるのですが、他にも使いたい時に何度も同じコードを書かなければならないのでmoduleに書いて呼び出すようにしてみました。

app/model/validate_common.rb

module ValidateCommon
  extend ActiveSupport::Concern
  included do
    def trim_space
      self.phone.gsub!(/[ \p{blank}\r\t\n\f]/, "")
    end
  end
end
app/model/user.rb
class User < ActiveRecord::Base
  include ValidateCommon
  # ... 省略 ...

  before_validation :trim_space
end

ただこのままだと電話番号にしか使用出来ない状態なので、app/model/user.rbの:trim_spaceに引数を持たそうとした時につまりました。

app/model/user.rb
class User < ActiveRecord::Base
  include ValidateCommon
  # ... 省略 ...

   before_validation -> {trim_space("phone", "email")}
end

このようにして書けば引数をもたせる事ができるので、DRYなコードにできるかと思います。
app/model/validate_common.rb側も少し編集します。

module ValidateCommon
  extend ActiveSupport::Concern
  included do
    def trim_space(*target_columns)
      target_columns.each do |target_column|
        if self.send(target_column)
          self.send(target_column).gsub!(/[ \p{blank}\r\t\n\f]/, "")
        end
      end
    end
  end
end

条件分岐の部分なのですが、 self.send(target_column)がnilの場合つまり今回だと電話番号、メール入力欄が何も入ってこない場合だとNoMethodError Exception: undefined method `gsub!' for nil:NilClassになるので書いています。

before_validationで書く時は基本シンボルの書き方でメソッドを書いていたので結構詰まりました。
後、sendメソッドのレシーバの持っているメソッドを呼び出すというのも知らなかったので非常に学びがありました。
他にも良い書き方あれば教えて欲しいです。

2017年振り返り

2017年は色々あった。特に仕事を辞めてプログラミングを始めた事が1番大きな事だった。今回はプログラミングを始めてどうだったか今の思いと振り返りをしていこうと思う。

なぜ仕事を辞めてプログラミングを始めたか?

自分は流れのままに生きてきてしまっていた気がする。学生時代も学びたい事もなく、とりあえず周りが大学進学してるし大学行こうって行ったし、そんな訳だから就職も特にしたい事もなく、なんとなく就活やってまあ受かったし行くかっていうよくありがちなダメな若者だった。ただ、就職してから、仕事も全く楽しくないし、この人生でいいのか?このまま流れのまま生きて行っていいのか?って自問自答していて、やっぱり自分のやりたいこと、楽しめることがしたいってなって前からプログラミングに興味があったのでそっちの道に進もうと思った。

やってみてどうだったか

プログラミングを始めたのは本当に良くて、勉強とか好きではなかったけど、今は休みがあったら自分の勉強としてコード書ける事が楽しいと思えるようになった。
ただ、挫折もあった。3ヶ月くらいかかってとりあえず動くものを作って、当たり前だけど、全然だなーって感じで、これ使う人いないよなって感じだった。そこから特に作りたいものなかったので、どうしようって感じだったし、2ヶ月くらい経ってまた作ろうってなったけど、今度は機能が多くなりすぎて、無理だ、、ってなって途中でやめてしまった。
反省点として本当に必要な機能からつくるべきだったし、最低限の機能を作って公開すれば良かったなと思う。

現在

今はアルバイトでエンジニアの仕事を2箇所でやっていて、フロントエンド中心に開発をしている。転職活動したけど、内定が出たのはそこまで行きたい企業じゃなかったし、行きたかった企業は落ちたので、アルバイトから始めて社員になるのが理想かなって思い今は技術力つけるために頑張っている。
ネットとか見てると、未経験で半年勉強してエンジニアなったとか、勉強始めて10ヶ月でエンジニアになった記事が結構あってそれに比べると自分はまだまだだなって思って辛い気持ちになったけど、今年は学ぶって事は楽しいって思えた事が収穫でエンジニアで生きて行く上で1番大事な事だと思うので、来年はもっと技術を学んでいこうと思っている。
最後に来年の目標として4つ

  • コードをしっかり書く時間を取る。
  • webアプリケーションを作って運用する。
  • アウトプット(ブログやLT)をする。
  • 定職につく。

これからはてなブログで技術の事も書いていこうと思うのでよろしくお願いします。