1日1%成長するブログ

毎日成長するために仕事/プライベートで得た学びをアウトプットするブログです

PaypalのAPIでRailsのアプリケーションと決済を照会できるようにする

Paypalの管理画面で表示される取引IDを取得するのは以下の通り。 このIDをRailsの管理画面で見れるようにしておけば決済の成功有無を参照できるようになる。

実際に運用し始めてから照会する方法が無いと困り、見つけた方法。

カード払い用のAPIの場合

developer.paypal.comhttps://developer.paypal.com/docs/api/orders/v2/#orders_capture

https://developer.paypal.com/docs/api/orders/v2/#definition-capture

response[:purchase_units][0][:payments][:captures][0][:id]のIDを取得する

Paypal払い用のAPIの場合 (定期払いのみ)

https://developer.paypal.com/docs/api/payments/v1/#definition-sale

response[:transactions][0][:related_resources][0][:sale][:id]のIDを取得する

ベイビーステップから学ぶメンタルコントロール (自覚編)

自分はベイビーステップというテニス漫画が大好きです。

少年マガジンで2007年〜2017年まで連載されていたので、 初連載時は今から13年前なのですが、未だによく読みます。

主人公のエーちゃんがノートでひたすらデータを貯めて改善して、 一歩ずつ成長していって強敵に立ち向かっていく姿がめちゃくちゃかっこいいんですよね。

面白いだけでなく、 人生レベルで役に立つエッセンスが色々詰まってるマンガだと思ってます。

特に自分みたいに不器用なタイプには、 ピッタリのロールモデルなので参考にしてます。

今回取り上げるのはメンタルコントロールです。 ベイビーステップの18巻でメンタルの状態には4つあるという話があります。

それが「無気力」・「怒り」・「重圧」・「挑戦」の4つです。

いい順番に並べ替えると、

「挑戦」←「重圧」←「怒り」←「無気力」

になります。

怒りは無気力よりはマシですが、勝利には直接結びつきません。 重圧は勝ちたいと思う心からくるものなので良いこと。

これを上手くコントロールして挑戦のメンタルに持っていくことが、 良いパフォーマンスを出す上でとても重要。

という話をしています。

このコントロールするのはまたスキルが必要になりますが、

まずは自分の今の状態を自覚して、 どの方向に向かっていくべきかを意識できるようになるだけでも、違います。

次回以降にはそれぞれのメンタル状態からいかにシフトさせていくか、について書いていきたいと思います。

Railsのコールバックをifで絞りつつ引数を指定する方法

before_xxx, after_xxxといったActiveRecordのコールバックを特定の条件で絞り込みしたい時は、 ifオプションを使うのが楽。

after_update :update_fuga, if: -> { saved_change_to_hoge_column? }

ただこれだとコールバックに引数を指定したい時に上手くいかない。 そういった場合は以下のようにラムダ式の中で自分でrubyのコードを書いてしまえばいい。

after_update -> { update_fuga("fuga") if saved_change_to_hoge_column? }

便利。

Railsで特定のカラムが更新された時だけバリデーションを実行する

Rails5.1からは特定のカラムが更新されたかどうかは、以下のメソッドで判定するようになった。

Save前

{カラム名}_changed?の代わりにwill_save_change_to_{カラム名}?
{カラム名}_was の代わりに {カラム名}_in_database

Save後

{カラム名}_changed?の代わりにsaved_change_to_{カラム名}?
{カラム名}_was の代わりに {カラム名} _before_last_save

今回はバリデーションなので、Save前のメソッドを使う。

validate :validate_update_hoge, if: :will_save_change_to_hoge?

def validate_update_hoge
  # hoge_in_databaseを使ってバリデーション書く
end

これでカラムが更新された場合のみ、変更前と後の値を使ってバリデーションを書ける。

Railsのupdateメソッドで特定の条件外でバリデーションをかける

特定の画面からの新規登録だけバリデーションをかけたいなど、 条件を絞ってバリデーションをかけたくなることはよくある。

そんな時は以下のようにsave時にcontextをオプションに渡してあげて、 with_optionsでその時に実行するバリデーションをまとめて設定すればいい。

with_options on: :create_context do
  validate :validate_create
end

user.save!(context: :create_context)

ただcontextオプションはupdateメソッドでは使えないので、 更新時で同じことをやりたい場合は、

以下のようにattributesにセットしてからsaveメソッドを使えば出来る。

user.attributes = update_params
user.save!(context: :update_context)

Rubyのアクセサメソッドを使ってEntityクラスを作ってAPIのレスポンスに使う

class HogePostsEntity
  attr_reader :author, :comments

  def initialize(post)
    @author = post.author
    @comments = post.comments
  end

  def self.collection(posts)
    posts.map { |post| new(post) }
  end
end

こんな感じでシンプルにEntity用のクラスを作れた。

render json: { status: 200, data: HogePostsEntity.collection(posts) }

APIのレスポンスの整形は全てEntityクラスに任せるようにすれば、 責務がハッキリするし、コントローラーがかなりスッキリしていい感じ。

RailsでFatControllerをリファクタリングしていく方針 (随時アップデート)

Viewで使うデータをどこで整形する?

  • DBから取得したデータを整形してハッシュの配列を用意するみたいな処理は置く場所に困る
  • Modelはvalidationやscope以外は対象テーブルの操作の処理以外は極力書くべきではないので適さない
  • Viewはslimを良く使うのでrubyシンタックスを使ってそこでだけ使うデータを整形したりもできるけど、どこで何を書いてるか後で追いづらい
  • コントローラーのprivateメソッドにするのは、分かりやすいけど、そうするとあっという間にFatControllerになっていく。。
  • そこでViewModel層を使うのが良さそう。Viewで使うデータを用意するのは全てViewModelに持っていく。
  • ViewModelの責務
    • ビューに渡すインスタンス変数を用意するクラス
    • before_actionでインスタンス変数をセットしていたようなコントローラーの処理を移行できる
    • ビューに渡すハッシュや配列といったデータはEntityで表現できると尚良さそう。
  • Entityの責務
    • Modelのデータを引数で渡すとビューで扱いたいデータの形式に変換するためのクラス
    • 一度共通で使えるEntityを作ってしまえば、至るところで同じような整形処理を書く手間がなくなる

複雑な検索クエリはどこで書く?

  • joinsしてwhereして..みたいな処理をコントローラーに書くと一気に行数が増えてしまう
  • 検索処理はscopeにしてModelに持たせる。
  • findする処理もコントローラーに書くのではなく対象のモデルに持たせるといい。

管理画面で必要とされるような複雑な検索機能はどこに書く?

  • 引数を受け取って存在する場合はwhereする (where if params[:hoge].present?)
  • のようなことを書いていると一気に膨れ上がる
  • DBに紐付かない検索用のモデルクラスを作ってそこに移行する (models/searchers/xxx_searcher.rb)