RailsのResourcesでNestしてshallow: trueしたresourcesをAngularJSの$resourceで扱う
例えばこういう感じのresourcesを定義したとする。
APIの例。newとeditは省いた。
# routes.rb namespace :api, defaults: { format: :json } do resources :reports, shallow: true do resources :comments, except: [:new, :edit] end end
定義されるルーティングはこうなる。reportsのは話に関係ないので省略
GET /api/reports/:report_id/comments(.:format) api/comments#index {:format=>:json} POST /api/reports/:report_id/comments(.:format) api/comments#create {:format=>:json} GET /api/comments/:id(.:format) api/comments#show {:format=>:json} PATCH /api/comments/:id(.:format) api/comments#update {:format=>:json} PUT /api/comments/:id(.:format) api/comments#update {:format=>:json} DELETE /api/comments/:id(.:format) api/comments#destroy {:format=>:json}
Railsではよくあるパターンだと思う。
このコメントのresourceをAngularJSの$resourceで使いたい。
$resourceでよく見かけるサンプルだとシンプルなものが多い.
こういったことは出来ないんだろうかと、AngularJSのリファレンスで$resourceの項目を見てみたら、ちゃんとやり方が書いてあった。
url – {string} – action specific url override. The url templating is supported just like for the resource-level urls.
$resourceの第3引数のactionsでurlをoverrideすればよいと。
やってみた。
下記はqueryとかsaveとか自動のやつは無視してRails的なactionを定義
# Comment.coffee 'use strict' angular.module('myApp') .factory 'Comment', ($resource) -> $resource("/api/comments/:commentId", {commentId: "@id", reportId: "@report_id"}, { index: {method: "GET", url: "/api/reports/:reportId/comments", isArray: true} create: {method: "POST", url: "/api/reports/:reportId/comments"} update: {method: "PATCH",params: {commentId: "@id"}} show: { method: "GET",params: {commentId: "@id"}} destroy: {method: "DELETE",params: {commentId: "@id"}} })
使う例
# sample.coffee angular.module('myApp') .controller "SampleCtrl", ($scope, $stateParams, Comment) -> $scope.comments = Comment.index(reportId: $stateParams.reportId) $scope.comment = new Comment(report_id: $stateParams.reportId) $scope.save = -> $scope.comment.$create((comment)-> # do something
上記の場合だと、report_idとreportIdでもにょってしまうので、サービス側でもう少しラップしてオブジェクトの引数ではなく、パラメータで渡した方が幸せになれるかもしれない。