Railsガイドにきちんと目を通して新しい知識を得る - バリデーション編 -

ドキュメントを読み込むのは大事、ということでRailsガイドを頭から読んでいく取り組みをしています。 各章ごとに、(Railsガイドにちゃんと書いてあるのに)知らなかった機能を雑にまとめていきます。

今回は、バリデーションの章です。  

railsguides.jp

upseart, upseart_all でバリデーションをスキップした更新

リンクはこちら

upsertというメソッドを知らなかったです。
特定の条件を満たすレコードがある場合はupdate, ない場合はinsertを行なってくれるメソッドのようです。
バリデーションをスキップするなど注意は必要ですが、ピッタリな使い道ができるケースもありそうです。

Product.upsert({ id: 4, price: 100 }, unique_by: :id)
# => idが4のレコードがあれば、priceを100に更新する。
# => idが4のレコードがなければ、新しく、idが4, priceが100のレコードを作成する

バリデーションメッセージのカスタマイズでオブジェクトとデータの引数を持つProcを渡せる

リンクはこちら

Stringを渡すことが多いと思うので、使う機会は限定的かもしれませんが、どこかで使えるかもと思いました。

class Product < ApplicationRecord
  validates :price, uniqueness: {
    scope: :name,
    message: -> (object, data) do
      "#{object.name}という商品名の#{data[:value]}円の商品は既に登録済み"
    end
  }
end
Product.create(name: 'sample', price: 100) # レコードを作成
product = Product.new(name: 'sample', price: 100)
product.valid?
# => false
product.errors.messages
# => {:price=>["sampleという商品名の100円の商品は既に登録済み"]}

# 上記バリデーションで、
# object には #<Product:0x0000000109bfd8d0 id: nil, created_at: nil, updated_at: nil, price: 100, name: "sample">
# data には {:model=>"Product", :attribute=>"Price", :value=>100}
# が入っている

strict: trueでvalid?などで例外を発生させる

リンクはこちら

valid?でfalseじゃなくて例外を返したいときが、想像しきれなかったのと、「?」で終わるメソッドで例外が返ってくるのがちょっと違和感がありました。

validates :name, presence: { strict: true }

Railsガイドにきちんと目を通して新しい知識を得る - マイグレーション編 -

ドキュメントを読み込むのは大事、ということでRailsガイドを頭から読んでいく取り組みをしています。 各章ごとに、(Railsガイドにちゃんと書いてあるのに)知らなかった機能を雑にまとめていきます。

今回は、マイグレーションの章です。

railsguides.jp

create_join_tableを使った多対多の中間テーブルの作成

リンクはこちら

railsチュートリアルでやるように、has_manyを使う方法しか知らなかったです。 この方法では、中間テーブルを明示的にはモデルとして扱わないので、用途は限定的かもしれませんが、機能として足りるときはスッキリ書けそうです。

ちなみに、各モデルにhas_and_belongs_to_manyを記述することで多対多の関係を記述できます。

class Product < ApplicationRecord
  has_and_belongs_to_many :categories
end

add_check_constraint で制約をつける

リンクはこちら

rails6.1から追加されたみたいです。 マイナスの値が入る可能性のないケースとかは結構あると思うので、使えそうです。

class AddPriceToProducts < ActiveRecord::Migration[7.0]
  def change
    add_column :products, :price, :integer
    add_check_constraint :products, "price > 0", name: "price_check"
  end
end
Product.create(price: -100)
# => ActiveRecord::StatementInvalid

revertでロールバックする

リンクはこちら

今までテーブルの削除時などdrop_tableで書いたりしてましたが、時短できるケースもありそうです。

以下のように書くことで、drop_tableと同じことをしていることになるみたいです。

class RevertCreateProducts < ActiveRecord::Migration[7.0]
  def change
    revert do
      create_table :products do |t|

        t.timestamps
      end
    end
  end
end

『オブジェクト指向でなぜつくるのか』を読んだ

 プログラミングの学習をしていた2年ほど前から積読されていた『オブジェクト指向でなぜつくるのか』をようやく読んだので簡単な感想を書いていきます。

bookplus.nikkei.com

オブジェクト指向が生まれた背景や、特徴を知ることができる

 本書は、オブジェクト指向が生まれた歴史的背景を説明しています。

 オブジェクト指向が生まれてから普及するまでに時間がかかった理由やオブジェクト指向が生まれた必然性(当初は実行効率が命だったが、ハードウェアの進歩によって再利用性等が重視されるようになった)はとても興味深い内容でした。

メモリの使い方を学べる

 5章では、オブジェクト指向の言語がメモリでどのように管理されているかについて記載されています。

 Javaを例に、クラスやメソッド情報は静的領域に、インスタンスはヒープ領域に確保されることなど、意識しきれていなかったメモリの使われ方について図で説明されているのも理解しやすかったです。

TDDやアジャイル等とオブジェクト指向との関係の話

 読んでいて、「そういえばそうか〜」となったのは、TDDやオブジェクト指向との親和性の話です。

 リファクタリングは既存の動いているコードに手を加えるということなので、影響範囲がどこまで広いかわからないコードではバグを生む可能性が高くなり、難しいですが、オブジェクト指向の特徴である凝集性や疎結合であるプログラミングだからこそ、リファクタリングを行うことができ、TDDのサイクルが効率よく回ります。TDDとオブジェクト指向をそういう目線で見たことがなかったので新鮮でした。

さいごに

 オブジェクト指向の特徴などは復習という感じでしたが、上記のような箇所で学びが多くておもしろかったです。

『アジャイルサムライ』の感想など

アジャイルサムライ』を読んだので、印象に残った点や感想を書いておこうと思います。

shop.ohmsha.co.jp

どんな本か?

  • アジャイルな開発とはどんなものか
  • アジャイルな開発で解決できる課題はどんなものか
  • 具体的に何をする必要があるのか

こういったことについて順序立てて分かりやすく書いてある本です。

印象に残った点と感想

 この本を読み終わって第一の感想は、アジャイル開発というのはかなり現実主義的な開発手法だなと感じました。

  • 顧客の要望は変わる
    • 顧客が開発にしっかり入ることが必要
  • やるべきことは常に時間と予算よりも多い
    • 「やらないこと」を決める
  • 前もって正確に見積もるのは無理
    • 期待マネジメントを適切に行うことが必要

 上記のような「現実問題こういうものだよね」という切り口から考えられている、実践的な手法の印象です。

「デモ」というシンプルで有効な手段

 細かい部分の話ですが、妙に納得したので書き残しておきます。

 自分の成果責任を自覚するための有効な方法として、「デモ」が紹介されており、なるほど〜と思いました。

 確かに定期的にデモすることが決まっており、その場で顧客に対して実際に作ったものを見せ、評価されるというのは間違いなく目標を意識することになるので、シンプルだけど有効な仕組み作りだなと思いました。

 デモは、顧客との確認/すり合わせの1つの段階くらいの認識でしたが、思った以上に効能がありそうだなというのは新たな発見でした。

直接的なコミュニケーションを想定よりも重視していた

 イメージと違ったのが、直接的なコミュニケーションをかなり重要視していたことです。例えば、働く場所は一致しておくべきということや、文書の力の限界を認識し、顧客と要望に関する対話を重視する、という記載があります。

 これは非常に納得感がある一方で、現状リモートワークも1つのスタンダードなスタイルとなっているので、その中でも効果的なやり方というのを工夫する必要がありそうです。(対面とリモートの会議の温度差の話はエンジニアに限らず散々記事や意見を見かけるので、かなり難しい問題とは思いますが)

さいごに 

 通勤等の時間を使ってスラスラと楽しく読むことができました。

 アジャイル開発の進め方の具体を知るのにはもちろん、開発者として最効率で価値を生み出すための意識の部分などもたくさん参考になることがあったので、よくお薦めの一冊として紹介されているのがよく理解できる本でした。

背伸びはキツいが役に立つ話

久々のブログになってしまいました。雑記です。

よく「役割や役職が人を育てる」という話を聞きますが、自分がそれを実感したのでつらつらと書いていこうと思います。

#CASE1 上司の不在で名前だけ昇進した話

 2年強前まで、私はプログラマーとは畑違いな事務系の仕事をしていました。そこで、部署配属早々に直属の上司がある事情で不在となったことがあります。

 その結果、(人員の関係で)新しい上司が来ることはなく、私が上司の役職を「借り」て上司がやっていたような振る舞いをすることになりました。

 その采配を決めた上司から「役職が人を育てるよ、きっとできる」と言われました。当時は「そんなこと言ってないで人員を補填してくれー!」と思っていたのを覚えています。

 名刺上もしっかり役職が上がりました。

部署外の人は知らないので背伸びをして案件に対応

 大きい組織で部署外の人はそんな事情を知らず、当然ながら肩書きで判断します。

 最初はプレッシャーに潰されそうになりましたが、時間が経つにつれて、自分の対外的な役職を自覚し、実力が足りないところはありながらも、背伸びをしてなんとか期待に応えようと動けるようになっていきました。

#CASE2 チームを引っ張るような立ち位置になった話

 これはつい最近の話ですが、新しく入られた方2人と合わせて3人でタッグを組んで開発を行うことになったことがありました。

 それまではそういった役割もなく、チームの1プログラマとして働いていました。ところが、上記のチーム編成になり、自分がPJに入ってからの期間も長いことから、必然的にメンバーのサポートをしながら、チームの開発の方針を考えていく立ち位置になりました。

 これも先ほどの話同様に、最初は不安しかなかったですが、いざ始まるとやらねばと覚悟し、なんとか不慣れながらも立ち位置を意識しながら行動できました。

背伸びはキツいが役に立つ、、、が、バランスが大事

 これらを通じて、「役割や役職が人を育てる」というのは悔しいけど間違っていない部分もあるなあと思っています。

 ただ、特にCASE1のように背伸びに追い込まれるのはちょっとキツさが強すぎるので、全肯定できない部分はありますし、少し間違えていればプレッシャーに潰されてしまっていたと思うので、バランスは大事ですね。私は運よく乗り越えられました。

 

 いずれにせよ、背伸びをせざるを得ない機会はチャンスと捉えてポジティブに頑張っていきたいなーという気持ちです。

(積読解消)3月に読んだ本と感想

3月に読んだ本の感想を簡単にまとめていきます。

メタプログラミングRuby(リベンジ)

www.oreilly.co.jp

 1年半ほど前に読んでみたのですが、当時の私には難しく挫折しました。

今回は、以下の点に気をつけて読みました。

  • どれだけ理解に時間がかかっても、わからないまま次に進まない。
  • なるべく手元で動かしながらゆっくり進める

 その結果、無事理解をしながら最後まで読み切ることができました。

正直、メタプログラミングできるか、と言われると怪しいですが、コードを読む上での心理的ハードルはかなり下がったのかなと思います。

個人的には、10章のActiveSupport::Concernが一番難しかったですが、なんとか読み切ることができました。

リーダブルコード

www.oreilly.co.jp

 言わずと知れた名著だと思いますが、これもきちんとすべて読んでなかったので読みました。

  • 変数の寿命を意識すること
  • 明確な命名をすること
  • タスクを分割すること

など、基本的かつ重要な考え方を総復習できました。

 10章の「プロジェクト固有のコードから汎用コードを分離する」というのは意識として足りてなかった気がするので、今後意識していこうと思います。

プログラムはなぜ動くのか

bookplus.nikkei.com

 2年弱前に買って積読になっていた本をようやく読みました。

 プログラムが動く仕組みを、メモリ・レジスタという部分から解説をしてくれます。この辺りの知識を体系的に学べていなかったので、とても勉強になりました。

 この本では、何度か「プログラムが動く仕組みをきちんと理解していないような、高水準言語の書き方しかわからないプログラマではいけない」という趣旨の記述があり、そうだよなあと胸に刺さりながら読んでいました。

Flutterハッカソンで3位入賞できました

先日、Flutterのハッカソンに参加しました。

flutterlabo.tech

結果としては、会社のメンバーと力を合わせて3位入賞することができました!

参加したきっかけ

 参加したきっかけは、会社の同僚がハッカソンを見つけて誘ってくれたことでした。

 Flutterについては、一度チュートリアルをやったことがあり、ちゃんとアプリを使ってみたいなーという気持ちはありつつ、なんだかんだできていなかったので、Flutterを学ぶいい機会だと思い、参加しました。

ハッカソンの1週間で作ったアプリ

 今回のハッカソンのテーマは「アナログなイベントをデジタル化する」でした。テーマ発表から、開発したアプリの発表&コード提出までの期間は1週間でした。

 私たちのチームがつくったアプリは「Talk to me(仮)」です。

 エンジニアは、紙の名刺以上にTwitterなどでつながることが多い職種な気がします。エンジニアがリアルのイベントで会った際の名刺交換に代わるサービスと位置付けて以下のようなアプリを作りました。

↓ 作ったアプリ(発表資料の一部を修正して抜粋)

私が担当した機能

 上記の中で、私は主に以下の機能を担当しました

  • アプリでQRコードリーダを立ち上げる機能
  • QRコードリーダーで読み取った内容をFirestoreに履歴として保存する機能
  • QRコードリーダーで読みとったデータに対するメモ機能
  • アカウント編集機能

 そのほか、画面スワイプでメニュー間を移動する機能など、モバイルアプリらしい部分も作ってみました。

部品を組み合わせる感じでできるので簡単で楽しい

 Flutterの見た目の部分は、Widgetと呼ばれる部品を組み立てて作るイメージで、割と思い通りに作れる感じで楽しかったです。

 スワイプでページ間を移動するなど、モバイルアプリっぽさを実装するのも用意されたWidgetを組み合わせて使えばすぐできるのも便利な点でした。

難しかった点

 リアルタイムでデータを取ってくるのが意外と大変でした。

 例えば、アカウント編集後に更新を押してアカウント表示画面に戻っても、「Firestoreのデータは更新されているが画面の情報が変わっていない」ことが起きました。

 画面で表示するデータの持ち方によっては、都度Firestoreからデータを持ってくるのではなく、以前の情報を使いまわしているため起きていたのですが、RailsアプリだとViewの表示ごとにControllerでデータを取得するのであまり見かけない現象だと思うので、最初は解決策がよくわかりませんでした。(最終的にはStreamBuilderというものを使って解決しました。)

課題はリファクタリング

 また、きれいにコードが書けたかと言われると否です。

  • Viewにロジックがたくさん書かれている
  • 同じコードが繰り返し出てくる
  • データを取得するだけなのに大袈裟なコードになっている(気がする)

 コードが汚いことを自覚しつつも、Dartへの理解が浅くてリファクタリングができないのは悔しい点でもありました。

さいごに

 ハッカソンなるものに初めて参加しましたが、アイデア出しから実装までできてよかったです。

 また、実装の時間は仕事終わりにとっていたのですが、チーム開発でやっていると他のメンバーの頑張りが刺激になってついつい夜遅くまで実装をしていました。大学生のころの試験期間のような気持ちになって、とても楽しかったです。

 まだアプリとしての完成度は低いので、細々とFlutterの開発を続けてリリースまでやりたいなあという気持ちです。