首先,我会为我破碎的英语和破碎的代码表示抱歉......(这里有很多单词来自谷歌翻译......所以,我担心我不能说清楚......所以,我粘贴所有代码......)
在rails中设置路由非常简单。但是当我们想把它变成angurjs时,它变得有点冗长......对于这类工作是否有任何“最佳实践”:
给出一些rails路由资源:
resources :users
resources :photos
...
resources :topics
如何在角度方面做到这一点?
这是我的方式(在咖啡脚本中,使用 angular 1.1.4 ):
# 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)
]
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循环中移动它,但是我无法弄清楚为什么...... 另一个问题是如何以干燥的方式设置嵌套资源
最后,感谢您的耐心等待,我会再次对不起... 但任何解决方案,建议或最佳做法? 我做错了吗?
答案 0 :(得分:3)
除了您对问题的描述非常复杂(大量代码)之外,我认为您错过了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)
答案 1 :(得分:0)
好吧,我弄清楚为什么解决方案的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
])
答案 2 :(得分:0)
我尽量避免复杂的服务,例如:
' /父母/:PARENT_ID /儿童/:ID'
我将其分为两种服务:
/父母/:PARENT_ID /儿童。对于GET(列表)和POST(内容中的Id)
然后我有
/ children / id为PUT,DELETE和单个GET