RailsでDBに配列Arrayを保存する

RailsでDBに配列を保存する方法

serialize :column_name を指定

RailsでDBに配列を保存する方法(サンプルコード)

class Hoge < ApplicationRecord
  serialize :arr
end

hoge = Hoge.new(arr: [1, 2, 3])
puts hoge.arr # => [1, 2, 3]

Arrayと明示するとこういう使い方もできるみたい

class Hoge < ApplicationRecord
  serialize :arr, Array
end

hoge = Hoge.new
hoge.arr << 1 << 2 << 3
puts hoge.arr # => [1, 2, 3]

Railsでprimary_keyとforeign_keyの両方を指定して主キーではないカラムで関連付けする

こんな関連付けのモデルがあったとして

class Atable < ApplicationRecord
  has_one :btable
  has_one :ctable
end

class Btable < ApplicationRecord
  belongs_to :atable
end

class Ctable < ApplicationRecord
  belongs_to :atable
end

bからcを呼び出すのに

Btable.find(1).atable.ctable

としなきゃいけないのはだるい

btables.atable_id = ctables.atable_id の条件で関連付けしたい

primary_key, foreign_keyを両方指定して関連付けをする

こうなる

class Atable < ApplicationRecord
  has_one :btable
  has_one :ctable
end

class Btable < ApplicationRecord
  belongs_to :atable
  has_one :ctable, primary_key: :atable_id, foreign_key: :atable_id
end

class Ctable < ApplicationRecord
  belongs_to :atable
  belongs_to :btable, primary_key: :atable_id, foreign_key: :atable_id
end

Huawei mate9でGoogleカレンダーの予定が勝手にキャンセル、辞退されるバグ

Huawei mate9にGoogleアカウントをひも付けたら勝手に他の人の予定をキャンセルや辞退させる問題がおきました。

調べてみるとHuaweiのデフォルトのカレンダーにG suiteのアカウントを連携させると発生するバグらしい。

なのでデフォルトカレンダーの権限をオフにして使わないようにします。

対処法

設定>アプリ>カレンダー>権限 を開いて各権限をOFFにする。 f:id:kuronekopunk:20170608112152p:plain

Googleカレンダーアプリなどの他のアプリを使うことになります。

参考サイト

【要注意】Huawei製スマホでGoogleカレンダーを使用する際の注意 - ゲームドライブ

他の方の記事を見るとHuawei P9をAndroid7.0にアップデートしたらひも付けていたG suiteアカウントで同じバグが発生したようです。

電話番号の正規表現はどうしたらいいのか

Railsのアプリを作っていて電話番号のバリデーションをするための正規表現はどう書いたらいいのか悩んだので調べてみました

※細かくやっていますが新しい電話番号や考慮されないパターンがあるかもなのでバリデーションは緩くしておくことをおすすめします。

電話番号の正規表現

日本の一般の電話番号の正規表現はこうなりそう

/\A(((0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1}|[5789]0[-(]?\d{4})[-)]?)|\d{1,4}\-?)\d{4}|0120[-(]?\d{3}[-)]?\d{3})\z/

想定している仕様

  • 0から始まる市外局番込の10桁の番号
  • [2-9]から始まる市外局番を含まない5~8桁の番号
  • 市外局番と市内局番は各1~4桁、合わせると5桁 になる
  • 携帯電話とPHSは「070」、「080」又は「090」から始まる11桁の番号
  • 市外局番、市内局番の境目で区切りが入る可能性がある 03-1234-1234
  • 区切りが市内局番を()で囲む可能性がある 03(1234)1234
  • フリーダイヤルは0120から始まる4桁3桁3桁

もしくは分けて

# 市外局番ありパターン
/\A0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1})[-)]?\d{4}\z/

# 市外局番なしパターン
/\A\d{1,4}\-?\d{4}\z/

# 携帯電話パターン
/\A0[5789]0[-(]?\d{4}[-)]?\d{4}\z/

# フリーダイヤルパターン
/\A0120[-(]?\d{3}[-)]?\d{3}\z/

を順次チェックしてマッチしなければという使い方でも分かりやすいかも

以下はこの正規表現にたどり着くまでの調査結果などです。

色々なサイトで電話番号の正規表現が違う

電話番号のバリデーションがしたく正規表現を探したけれどサイトごとにバラバラ…
なんなら考慮されていないパターンがあったり…

# 【電話番号】半角数字で入力されているか
/^[0-9]+$/

# 【電話番号】半角ハイフンを含んだ1〜4桁・1〜4桁・3〜4桁の半角数字の形式で入力されているか
/^0\d{1,4}-\d{1,4}-\d{3,4}$/

http://designsupply-web.com/knowledgeside/1640/

色んなパターン書いて結局どれ使うんだっていうのが悩ましいサイトやら

/^¥d{3}-¥d{4}$|^¥d{3}-¥d{2}$|^¥d{3}$/
/^¥d{3}¥-¥d{4}$/

/^¥d{3}-¥d{4}-¥d{4}$|^¥d{11}$/
/^0¥d0-¥d{4}-¥d{4}$/

/^[0-9-]{6,9}$|^[0-9-]{12}$/
/^¥d{1,4}-¥d{4}$|^¥d{2,5}-¥d{1,4}-¥d{4}$/

http://befine.jugem.jp/?eid=29

03-1234-1234 だけでなく 03(1234)1234 も通すパターンがあったり

/\d{2,5}[-(]\d{1,4}[-)]\d{4}/

http://qiita.com/jnchito/items/893c887fbf19e17d3ff9#%E9%9B%BB%E8%A9%B1%E7%95%AA%E5%8F%B7%E3%82%92%E6%8E%A2%E3%81%99

そのそも電話番号のパターンはどういうのがあるのか

基本的な仕様

総務省が電話番号に関しての説明を公開していました。

f:id:kuronekopunk:20170531181426p:plain

総務省|電気通信番号の利用・指定|電話番号に関するQ&A

国内の一般の電話番号だけであれば

  • 0から始まる市外局番込の番号
  • [2-9]から始まる市外局番を含まない番号

の2パターンでよさそう

また市外局番+市内局番は5桁と決まっている模様

携帯電話

携帯電話とPHSは「070」、「080」又は「090」から始まる11桁の番号です。

総務省|電気通信番号の利用・指定|電話番号に関するQ&A

9桁の電話番号?

電話番号が、頭の0と局番を含め9桁であるもの。現在では一つも残されていない。
かつて東京(03)と大阪(06)が、9桁の電話番号地域として有名だったが、番号の逼迫に対応するため、次のように一桁増やして10桁化するよう、変更されている。

電話番号の桁数 | ただの作業メモ

9桁の電話番号 ‐ 通信用語の基礎知識

仕様を確認して正規表現を作ってみる

  • 0から始まる市外局番込の10桁の番号
  • [2-9]から始まる市外局番を含まない5~8桁の番号
  • 市外局番と市内局番は各1~4桁、合わせると5桁 になる
  • 携帯電話とPHSは「070」、「080」又は「090」から始まる11桁の番号
  • 市外局番、市内局番の境目で区切りが入る可能性がある 03-1234-1234
  • 区切りが市内局番を()で囲む可能性がある 03(1234)1234

まず市外局番込の10桁の正規表現を作る

必要そうなのはこのあたり

  • 0から始まる市外局番込の10桁の番号
  • 市外局番と市内局番は各1~4桁、合わせると5桁 になる
  • 市外局番、市内局番の境目で区切りが入る可能性がある 03-1234-1234
  • 区切りが市内局番を()で囲む可能性がある 03(1234)1234

想定パターン

  • 01-1234-1234
  • 012-123-1234
  • 0123-12-1234
  • 01234-1-1234
  • 01(1234)1234
  • 012(123)1234
  • 0123(12)1234
  • 01234(1)1234
  • 0123456789
/\A0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1})[-)]?\d{4}\z/

市外局番抜きもマッチするように変更

想定パターン

  • 1234-1234
  • 123-1234
  • 12-1234
  • 1-1234
  • 12345
/\A((0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1})[-)]?)|\d{1,4}\-?)\d{4}\z/

050, 070, 080, 090から始まる11桁もマッチするように変更

/\A((0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1}|[5789]0[-(]?\d{4})[-)]?)|\d{1,4}\-?)\d{4}\z/

フリーダイヤルもマッチするように変更

4桁3桁3桁

  • 0120-123-123
/\A(((0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1}|[5789]0[-(]?\d{4})[-)]?)|\d{1,4}\-?)\d{4}|0120[-(]?\d{3}[-)]?\d{3})\z/
# rubyで検証
a = ['01-1234-1234','012-123-1234','0123-12-1234','01234-1-1234','01(1234)1234','012(123)1234','0123(12)1234','01234(1)1234','0123456789','1234-1234','123-1234','12-1234','1-1234','12345','050-1234-1234','070-1234-1234','080-1234-1234','090-1234-1234','0120-525-256','0120117117','1234567890','012345678','01234567890']

pattern = /\A(((0(\d{1}[-(]?\d{4}|\d{2}[-(]?\d{3}|\d{3}[-(]?\d{2}|\d{4}[-(]?\d{1}|[5789]0[-(]?\d{4})[-)]?)|\d{1,4}\-?)\d{4}|0120[-(]?\d{3}[-)]?\d{3})\z/

a.each {|e| puts e unless e =~ pattern }

# => 1234567890
# => 012345678
# => 01234567890

桁数が違うものや桁数が合っていても0から始まらないものだけが出力されることを確認しました。

もうこうれでいいんじゃないだろうか…