例えばこういう感じの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でもにょってしまうので、サービス側でもう少しラップしてオブジェクトの引数ではなく、パラメータで渡した方が幸せになれるかもしれない。