4年ほど乗っている5万円のクロスバイクのオーバーホールに本体代くらいの費用がかかりそうなのでいっそロードバイクに買い換えようか悩んでいるstreampackチームのminsuです。

やりたいこと

rails APIへ次のようなformを送ったときに、
apipie-railsのcustom validatorを設定してformのfileタイプをパラメーターとして扱えるようにします。

<form method="post" action="xxxx" enctype="multipart/form-data">
  <p>画像ファイル<input type="file" name="imagefile" accept="image/*"></p>
  <p><input type="submit" value="送信する"></p>
</form>

apipie-railsgem
https://github.com/Apipie/apipie-rails

apipie-railsは、railsの REST API向けのドキュメント生成のためのツールで、
次のようにアクションごとにエラーコードやパラメーターがドキュメント表示できます。

バリデーター

コードを記載するとドキュメント側に反映されるとともに、
apipie-railsがリクエストパラメータをチェックしてドキュメントで指定した以外のフォーマットの場合にバリデーションエラーを返すという機能が付いています。
バリデーターは型の指定や配列、ハッシュなどapipie側で使いやすいものがすでに用意されているのですが、formのfileタイプに対応できるバリデーターはありません。

カスタムバリデーター

しかし、apipieでは独自にバリデーターを設定することができるのでformのfileタイプを扱えるカスタムバリデーターを実装していきましょう。
https://github.com/Apipie/apipie-rails#adding-custom-validator

カスタムバリデーターは initializars で設定できるため、
config/initializars/apipie_validators.rb を作成して次のclassを設定します。

apipie_validators.rb

class UploadedFileValidator < Apipie::Validator::BaseValidator

  def validate(value)
    value.is_a?(ActionDispatch::Http::UploadedFile)
  end

  def self.build(param_description, argument, options, block)
    self.new param_description if argument == :uploadedfile
  end

  def description
    'Must be a valid file'
  end

end

そしてapipieでパラメーターの記述で、さっきカスタムバリデーターで設定した :uploadedfile を指定してあげるとバリデーションチェックで ActionDispatch::Http::UploadedFile クラスなのかをチェックしてくれるようになります。

param :imagefile, :uploadedfile, :required => true ,:desc => "Need to set a new user image file in form-data"

これでapipie-railsでformのfileタイプが扱えるようになりました。

おまけ

カスタムバリデーターを作らなくても次のようにパラメーターに直接 ActionDispatch::Http::UploadedFile クラスを指定することでも同じようなことができるのですが

param :imagefile, ActionDispatch::Http::UploadedFile, :required => true ,:desc => "Need to set a new user image file in form-data"

ドキュメントの記述がこのように

Must be a ActionDispatch::Http::UploadedFileとなるので、ドキュメントを読む側がなんのこっちゃになりそうです。

元記事はこちら

apipie-rails で multipart/form-data を扱う