たぬきエンジニア日記

神奈川の自社開発企業にてエンジニアをしているたぬきの日記。現在エンジニア歴は1年ほど。学習の発信を気ままにしている日記です。

Rails でネストしたフォームを作っていたら Procとlambdaが出てきた話。

こんにちは。すごーく久しぶりの日記です。

なぜかというと、Qiitaに書くまででもなく、Twitterにかける分量でもなく、ただ、アウトプットして記憶に残しておきたいことが出てきたためです。。。。

これからも、何か思いついたらこちらに書くかも、書かないかも。。。。。 いや、この記事をQiitaに引っ越すのかな。。。。???

本日遭った難しめのコード

本日、ネストしたフォームを書いていたら、以下のようなコードに出会いました。 (以下、Railsガイドからの該当箇所の引用です。)

class Person < ApplicationRecord
  has_many :addresses
  accepts_nested_attributes_for :addresses, reject_if: lambda {|attributes| attributes['kind'].blank?}
end

そして、このコードには、こんな説明がついていました。

ユーザーが何も入力しなかったフィールドを無視できれば何かと便利です。これは、:reject_if procをaccepts_nested_attributes_forに渡すことで制御できます。

うーん。。。。。読めぬ。。。。

実は、proclambdaも、以前、『チェリー本』を学習した際に、わからないまま終わっていたところなのでした。。。。

頑張って読み直してみた

良い機会なので、これを機に、チェリー本を読み返しますと、このように書いてありました。

Procクラスはブロックをオブジェクト化するためのクラスです

どういうことかというと、下記のようなコードがあった場合、

add_proc = Proc.new { | a, b | a + b }
add_proc.call(10, 20)
#=> 30

という風に、処理を変数(ここではadd_proc)の中に入れることができます。そしてadd_procは引数としてほかのメソッドで使えたりもします。

また、lambda については以下のような説明がありました。

Proc.newとラムダはほぼ同じものなのですが…

ほぼ同じものなのですね。lambdaはこのように書けるようです。

# こちらの2行は同じ内容を表すコード
->(a, b) { | a, b | a + b }
lambda { | a, b | a + b }

なお、『チェリー本』内では、実際の細かい挙動の違いまで丁寧に紹介されていましたが、ここでそれに立ち入るのは本質ではないので、ここまでにします。

再度、読解

改めて、最初にわからなかったコードを見てみます。

▽コード

class Person < ApplicationRecord
  has_many :addresses
  accepts_nested_attributes_for :addresses, reject_if: lambda { | attributes | attributes['kind'].blank? }
end

▽説明文

ユーザーが何も入力しなかったフィールドを無視できれば何かと便利です。これは、:reject_if procをaccepts_nested_attributes_forに渡すことで制御できます。このprocは、フォームから送信された属性のハッシュ1つ1つについて呼び出されます。

:reject_ifの定義が見つからなかったのですが、つまり、:reject_ifはprocオブジェクトで、そこに何らかの処理が格納されている。そして、処理の内容が lambda { | attributes | attributes['kind'].blank? } ということのようです。

ちなみに、上記のコードは、ネストした構造のフォームがあったとき、たとえ子テーブルに格納するデータが空欄のままSubmitボタンが押されても、空欄のデータを作成しないコードです。

おわり

半年前に書籍に取り組んだ時には、「なにこれ?わからない!」と投げ出した箇所ですが、時間がたって見返してみると理解できるようになっているものですね^^ ちょっとうれしかった今日この頃でした。