我们如何以干燥的方式使用带有angularjs的rails路由?

首先,我会为我破碎的英语和破碎的代码表示遗憾……(这里有很多单词来自谷歌翻译……所以,我担心我不能说清楚……所以,我粘贴所有代码…)

在rails中设置路由非常简单。 但是当我们想把它变成angurjs时,它会变得有点冗长……对于这类工作是否有任何“最佳实践”:

给出一些rails路由资源:

resources :users resources :photos ... resources :topics 

怎么做有角度的一面?

这是我的方式(在咖啡脚本中,使用角度1.1.4 ):

以Rails方式使用RESTful服务:

 # angular/services/restful.js.coffee # RESTful resource following Rails route's convention # index: GET '/resource.json' # save: POST '/resource.json' # get: GET '/resource/:id.json' # update: PUT '/resource/:id.json' # edit: GET '/resource/:id/edit.json' # new: GET just use get, id: 'new' app.factory('RESTful', ['$resource', ($resource)-> (resource_name) -> url = "/#{resource_name}/:id:format" defaults={format: '.json', id: '@id'} actions = { index: id: '' url: "/#{resource_name}:format" method: 'GET' isArray:false edit: url: "/#{resource_name}/:id/edit:format" method: 'GET' update: method: 'PUT' save: url: "/#{resource_name}:format" method: 'POST' } $resource url, defaults, actions ]) # index: GET '/parents/:parent_id/children.json' # save: POST '/parents/:parent_id/children.json' # get: GET '/parents/:parent_id/children/:id.json' # update: PUT '/parents/:parent_id/children/:id.json' # edit: GET '/parents/:parent_id/children/:id/edit.json' # new: GET just use get, id: 'new' app.factory('NESTful', ['$resource', ($resource)-> (parents, children) -> # naive singularize parent = parents.replace(/s$/, '') url = "/#{parents}/:#{parent}_id/#{children}/:id:format" defaults={ format: '.json', id: '@id' } actions = { index: id: '' url: "/#{parents}/:#{parent}_id/#{children}:format" method: 'GET' isArray:false edit: url: "/#{parents}/:#{parent}_id/#{children}/:id/edit:format" method: 'GET' update: method: 'PUT' save: url: "/#{parents}/:#{parent}_id/#{children}:format" method: 'POST' } $resource url, defaults, actions ]) 

路线:

 app.config(['$routeProvider', '$locationProvider', ($routeProvider, $locationProvider) -> $locationProvider.html5Mode(true) # general RESTful routes resource_list = ['users', 'photos', 'topics'] for resource in resource_list # naive singularize singular = resource.replace(/s$/, "") captialize = singular.charAt(0).toUpperCase() + singular.slice(1) $routeProvider .when "/#{resource}", templateUrl: "/tp/#{resource}/index" controller: "#{captialize}IndexCtrl" resolve: index: ["#{captialize}Loader", (Loader)-> Loader('index')] .when "/#{resource}/new", templateUrl: "/tp/#{resource}/edit" controller: "#{captialize}NewCtrl" resolve: resource: ["#{captialize}Loader", (Loader)-> Loader('new')] .when "/#{resource}/:id", templateUrl: "/tp/#{resource}/show" controller: "#{captialize}ShowCtrl" resolve: resource: ["#{captialize}Loader", (Loader)-> Loader('show')] .when "/#{resource}/:id/edit", templateUrl: "/tp/#{resource}/edit" controller: "#{captialize}EditCtrl" resolve: resource: ["#{captialize}Loader", (Loader)-> Loader('edit')] # special routes $routeProvider .when '/', templateUrl: '/tp/pages/home' controller: 'PageCtrl' .otherwise({redirectTo: '/'}) ]) 

控制器应该是超级干净的,然后我们可以专注于商业

 app.controller 'UserShowCtrl', ['$scope', 'resource' ($scope, resource)-> $scope.user = resource.user ] app.controller 'UserIndexCtrl', ['$scope', 'index', ($scope, index) -> $scope.users = index.resource.users $scope.total_pages = index.pages.total_pages $scope.currentPage = index.pages.current_page getPage = (page)-> index.resource.$index page: page (resource, headers)-> $scope.users = resource.users $scope.$watch 'currentPage', (newval)-> getPage(newval) ] 

问题出在Loader for resolve obj中:

 app.factory('UserLoader', ['RESTful', '$route', '$q', (RESTful, $route, $q) -> (action)-> model = 'users' delay = $q.defer() fetcher = RESTful(model) switch action when 'index' fetcher.index page: $route.current.params.page (resource, headers)-> delay.resolve resource: resource pages: JSON.parse(headers('X-Pagination')) (resource)-> delay.reject "Unable to fetch #{model} index" when 'show' fetcher.get id: $route.current.params.id (resource)-> delay.resolve(resource) (resource)-> delay.reject "Unable to fetch #{model} #{$route.current.params.id}" when 'edit' fetcher.edit id: $route.current.params.id (resource)-> delay.resolve(resource) (resource)-> delay.reject "Unable to fetch #{model} #{$route.current.params.id} edit" when 'new' fetcher.get id: 'new' (resource)-> delay.resolve(resource) (resource)-> delay.reject "Unable to fetch #{model} new" return delay.promise ]) 

这里有两个问题:第一个问题是我必须复制&&粘贴上面的加载器代码然后gsub(’user’,’photo’)等…(实际上只改2个字,但我讨厌复制&&粘贴..)我已经尝试在for循环中移动它,但是我无法弄清楚为什么……另一个问题是如何以干燥的方式设置嵌套资源

最后,感谢您的耐心,我会再次对不起……但是任何解决方案,建议或最佳做法? 我做错了吗?

除了你对这个问题的描述非常复杂(大量代码)之外,我认为你错过了REST API概念。

您正在将Rails后端资源(及其路由)与客户端路由混合在一起。 这是错误的恕我直言。 您的前端应用程序路由不应该在REST路由上跳跃(阴影)。 如果您要获取users资源(例如GET /users/5.json ),则不应将客户端导航到/tp/users/show 。 您的REST和客户端路由是两个独立的独立抽象。

你的客户端路线应该是这样的

 / /userprofile /dashboard /articles/2013?page=4 

坐在这些路由上的控制器应该使用您的资源服务从REST API获取所需的数据,如下所示:

 angular.module('myApp').controller 'UserProfileController', ($scope, userResource) -> $scope.user = userResource.query({id: SOME_ID}) angular.module('myApp.resources').factory 'userResource', ($resource) -> params = { id: '@id' subItem: '@subItem' subItemId: '@subItemId' } actions = { query: { method: 'GET' params: {} isArray: true } ban: { method: 'POST' params: {banned: true} } } return $resource('/api-1.0/users/:id/:subItem/:subItemId', params, actions) 

好吧,我弄清楚为什么解决方案的Loader不能按预期工作……关键是angularjs服务是一个sigleton。 它不起作用,因为我把循环放在第一个版本的服务定义中…

为了排序,这工作:

 angular.forEach [ ['profile', 'profile'] ['user', 'users'] ['avatar', 'avatars'] ], (resouce_definition)-> resource = resouce_definition[1] singular = resouce_definition[0] captialize = singular.charAt(0).toUpperCase() + singular.slice(1) app.factory("#{captialize}Loader", [ 'RESTful', '$route', '$q' (RESTful, $route, $q)-> (action)-> delay = $q.defer() id = $route.current.params.id fetcher = RESTful(resource) switch action when 'index' fetcher.index page: $route.current.params.page (response, headers)-> delay.resolve resource: response pages: JSON.parse(headers('X-Pagination')) (response)-> delay.reject "Unable to fetch #{resource} index" when 'show' fetcher.get id: id (response)-> delay.resolve(response) (response)-> delay.reject "Unable to fetch #{resource} #{id}" when 'edit' fetcher.edit id: id (response)-> delay.resolve(response) (response)-> delay.reject "Unable to fetch #{resource} #{id}" when 'new' fetcher.get id: 'new' (response)-> delay.resolve(response) (response)-> delay.reject "Unable to fetch #{resource} new" return delay.promise ]) 

我尽量避免复杂的服务,例如:’/ parents /:parent_id / children /:id’
我将其分为两个服务:
/父母/:PARENT_ID /儿童。 对于GET(列表)和POST(内容中的Id)然后我有/ children / id用于PUT,DELETE和单个GET