この記事で書く事
railsを使って外部から参照されるapiを実装しようとしたときに、モデルに書きたくない処理が必要になり、それをどこにおくか、を考えた時に学んだ事。
この記事で書かない事
細かいrailsでのそもそものapiの実装方法について
悩んだこと、考えたこと
アプリケーションA自体が持つモデルに対しての処理に関係ない、外部アプリケーションBから呼び出されるapiに対しての処理を、モデルに書いてもいいのかどうか。
限定的に呼び出される処理を隔離したかった。
moduleに切り出す方法が最初はパッと浮かんだ。
ただ、それをやると、他のapiでもそのモデルに対しての処理でその内容が参照されてしまう。
そしてアプリケーションで使用されるこのモデルのインスタンス全てにその属性が参照可能になってしまう。
active_model_serializersを使ってみる
controller
class API::UsersController
def index
render json: @users, serializer: ActiveModelSerializers,
each_serializer: user_client_serializer
end
end
model
# :id, :name, :imageを列にもつ
class User
# 細かいmodelの中身は省略
end
serializer
class UserClientSerializer
attributes :id, :name, :image # 全てのuserにひもづくattrを参照可能に
attribute :user_type # このserializerだけが必要とするattrを追加
def user_type # 特定のapi固有の属性で、モデルには書きたくない....
return 0 if object.image.present?
1
end
end
簡易な表記にしたのでこのままでは動きませんが、こうすることで、model自体にapi固有の処理を書かずに済みました。
別のapi経由でもuserを渡すことになったときに、今回例としてあげたuser_typeが不要だった場合は、以下のserializerを準備してあげることで、モデルに手を加えることなく、対応が可能です。
serializer
class UserSerializer
attributes :id, :name, :image
end
この作業をするまで、active_model_serializersを使ったことはなく、勉強になりました。