angular-rails 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -50
- data/lib/angular-rails/version.rb +1 -1
- data/lib/generators/angular/install/install_generator.rb +1 -1
- data/test/angular-rails_test.rb +2 -1
- data/test/dummy/log/test.log +1 -0
- data/test/dummy/tmp/cache/assets/D39/900/sprockets%2Fb8870fba4613fc84863ba75d021a0fb8 +0 -0
- data/test/dummy/tmp/cache/assets/D9F/C50/sprockets%2Ff1c6daf537a49ce6c96ef829b3000ad3 +0 -0
- data/test/generators/install_generator_test.rb +1 -1
- data/test/tmp/app/assets/javascripts/application.js +1 -1
- data/vendor/assets/javascripts/angle-up.js +149 -0
- metadata +11 -7
- data/vendor/assets/javascripts/angular-helpers.coffee +0 -62
data/README.md
CHANGED
@@ -47,58 +47,10 @@ So far we have a controller generator which generates a controller file if you r
|
|
47
47
|
|
48
48
|
This file is empty except for the class declaration, but I will be adding some RESTful controller functionality shortly.
|
49
49
|
|
50
|
-
##
|
50
|
+
## angle-up
|
51
51
|
|
52
|
-
In an attempt to DRY up angular apps I added an angular-helpers coffeescript file to the assets path. So far it has a Router superclass for your main application router. If you subclass it in Coffeescript like so:
|
53
52
|
|
54
|
-
|
55
|
-
routes:->
|
56
|
-
{
|
57
|
-
default: '/photographers'
|
58
|
-
'/photographers':
|
59
|
-
template: '<%= asset_path("photographers.html") %>'
|
60
|
-
controller: PhotographersCtrl
|
61
|
-
'/photographers/:photographer_id/galleries':
|
62
|
-
template: '<%= asset_path("galleries.html") %>'
|
63
|
-
controller: GalleriesCtrl
|
64
|
-
'/photographers/:photographer_id/galleries/:gallery_id/photos':
|
65
|
-
template: '<%= asset_path("photos.html") %>'
|
66
|
-
controller: PhotosCtrl
|
67
|
-
}
|
68
|
-
|
69
|
-
You will have those routes set up. All this class needs is a member function called `routes` that returns a hash of routing information.
|
70
|
-
|
71
|
-
Note that this class will need to be injected with both the $xhr and the $route object like so:
|
72
|
-
|
73
|
-
PhotoGalleryCtrl.$inject = ['$route', '$xhr']
|
74
|
-
|
75
|
-
This is because it sets us some CSRF preventions using $xhr as well. Note that this information gets thrown into the controller scope, so `@$xhr` and `@$router` are available in inheriting controllers as well (regardless if inheriting explicitly (through `extends`) or implictly (by being nested in a deeper view tag)).
|
76
|
-
|
77
|
-
Much of this is ripped from a demo by [Daniel Nelson](https://github.com/centresource/angularjs_rails_demo).
|
78
|
-
|
79
|
-
Another thing added is a `resourceService` function. This function is called like:
|
80
|
-
|
81
|
-
resourceService 'Photos', 'photographers/:photographer_id/galleries/:gallery_id/photos', 'index'
|
82
|
-
resourceService 'SelectedPhotos', 'selected_photos/:selected_photo_id'
|
83
|
-
|
84
|
-
This sets up angular services for the listed paths. Also add to the end all the actions that you want it to support. So far the accepted actions are 'index', 'update', 'create' and 'destroy'. If you leave off all actions, it will automatically assume that you want to support all 4.
|
85
|
-
|
86
|
-
This helper file adds some features to help parse results.
|
87
|
-
|
88
|
-
* An `AngularModel` class. All classes that inherit from this may be used to wrap the results returned from angular. They also allow you to map hasMany associations like so (haven't needed belongsTo yet myself):
|
89
|
-
|
90
|
-
class @Todo extends AngularModel
|
91
|
-
schedule:(procrastinationTime)-> # postpone to future
|
92
|
-
|
93
|
-
class @TodoList extends AngularModel
|
94
|
-
hasMany:
|
95
|
-
todos: Todo
|
96
|
-
|
97
|
-
* An `autowrap` function added to global namespace. This function takes a class to wrap the resource result in and optionally takes a function to pass it in to (i.e. if you need a real success function). This function is passed in as the success function like so:
|
98
|
-
|
99
|
-
@all_todo_lists = TodoListService.get {}, autowrap(TodoList)
|
100
|
-
|
101
|
-
A final thing added to this helper file is initialization of angularjs. This way, if angularjs is added to asset pipeline, no `ng:autobind` tag needs to be (or should be) added.
|
53
|
+
In an attempt to DRY up angular apps I added the angle-up javascript file to the assets path. [angle-up](https://github.com/ludicast/angle-up) attempts to add some opinions to angular apps.
|
102
54
|
|
103
55
|
## Example Usage
|
104
56
|
|
@@ -14,7 +14,7 @@ module Angular
|
|
14
14
|
|
15
15
|
def inject_angular
|
16
16
|
append_to_file "app/assets/javascripts/application.js" do
|
17
|
-
"//= require angular.min\n//= require
|
17
|
+
"//= require angular.min\n//= require angle-up\n//= require_tree ./angular\n"
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
data/test/angular-rails_test.rb
CHANGED
@@ -9,6 +9,7 @@ class AngularRailsTest < ActiveSupport::TestCase
|
|
9
9
|
assert_not_nil @app.assets["angular.min"]
|
10
10
|
end
|
11
11
|
test "angular-helpers.coffee is found as an asset" do
|
12
|
-
assert_not_nil @app.assets["
|
12
|
+
assert_not_nil @app.assets["angle-up"]
|
13
|
+
puts @app.assets["angle-up"]
|
13
14
|
end
|
14
15
|
end
|
data/test/dummy/log/test.log
CHANGED
Binary file
|
Binary file
|
@@ -51,7 +51,7 @@ class InstallGeneratorTest < Rails::Generators::TestCase
|
|
51
51
|
run_generator
|
52
52
|
|
53
53
|
assert_file "app/assets/javascripts/application.js" do |application|
|
54
|
-
assert_match /require angular.min(.*)require
|
54
|
+
assert_match /require angular.min(.*)require angle-up(.*)require_tree \.\/angular/m, application
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -0,0 +1,149 @@
|
|
1
|
+
|
2
|
+
(function() {
|
3
|
+
var __slice = Array.prototype.slice;
|
4
|
+
|
5
|
+
this.Router = (function() {
|
6
|
+
|
7
|
+
Router.prototype.initRoutes = function(routes) {
|
8
|
+
var info, routeName;
|
9
|
+
for (routeName in routes) {
|
10
|
+
info = routes[routeName];
|
11
|
+
if (routeName === "default") {
|
12
|
+
this.$route.otherwise({
|
13
|
+
redirectTo: info
|
14
|
+
});
|
15
|
+
} else {
|
16
|
+
this.$route.when(routeName, {
|
17
|
+
template: info.template,
|
18
|
+
controller: info.controller
|
19
|
+
});
|
20
|
+
}
|
21
|
+
}
|
22
|
+
return this.$route.parent(this);
|
23
|
+
};
|
24
|
+
|
25
|
+
Router.prototype.setupXhr = function() {
|
26
|
+
var token;
|
27
|
+
this.$xhr.defaults.headers.post['Content-Type'] = 'application/json';
|
28
|
+
this.$xhr.defaults.headers.put['Content-Type'] = 'application/json';
|
29
|
+
if (token = $("meta[name='csrf-token']").attr("content")) {
|
30
|
+
this.$xhr.defaults.headers.post['X-CSRF-Token'] = token;
|
31
|
+
this.$xhr.defaults.headers.put['X-CSRF-Token'] = token;
|
32
|
+
return this.$xhr.defaults.headers['delete']['X-CSRF-Token'] = token;
|
33
|
+
}
|
34
|
+
};
|
35
|
+
|
36
|
+
function Router($route, $xhr) {
|
37
|
+
this.$route = $route;
|
38
|
+
this.$xhr = $xhr;
|
39
|
+
this.setupXhr();
|
40
|
+
this.initRoutes(this.routes());
|
41
|
+
}
|
42
|
+
|
43
|
+
return Router;
|
44
|
+
|
45
|
+
})();
|
46
|
+
|
47
|
+
this.resourceService = function() {
|
48
|
+
var commandHash, methods, path, serviceName, type, _i, _len;
|
49
|
+
serviceName = arguments[0], path = arguments[1], methods = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
|
50
|
+
if (methods.length === 0) {
|
51
|
+
methods.push('index', 'create', 'update', 'destroy', 'show');
|
52
|
+
}
|
53
|
+
commandHash = {};
|
54
|
+
for (_i = 0, _len = methods.length; _i < _len; _i++) {
|
55
|
+
type = methods[_i];
|
56
|
+
commandHash[type] = (function() {
|
57
|
+
switch (type) {
|
58
|
+
case 'index':
|
59
|
+
return {
|
60
|
+
method: 'GET',
|
61
|
+
isArray: true
|
62
|
+
};
|
63
|
+
case 'show':
|
64
|
+
return {
|
65
|
+
method: 'GET',
|
66
|
+
isArray: false
|
67
|
+
};
|
68
|
+
case 'create':
|
69
|
+
return {
|
70
|
+
method: 'POST'
|
71
|
+
};
|
72
|
+
case 'update':
|
73
|
+
return {
|
74
|
+
method: 'PUT'
|
75
|
+
};
|
76
|
+
case 'destroy':
|
77
|
+
return {
|
78
|
+
method: 'DELETE'
|
79
|
+
};
|
80
|
+
}
|
81
|
+
})();
|
82
|
+
}
|
83
|
+
return angular.service(serviceName, function($resource) {
|
84
|
+
return $resource(path, {}, commandHash);
|
85
|
+
});
|
86
|
+
};
|
87
|
+
|
88
|
+
angular.element(document).ready(function() {
|
89
|
+
return angular.compile(document)().$apply();
|
90
|
+
});
|
91
|
+
|
92
|
+
this.AngularModel = (function() {
|
93
|
+
|
94
|
+
function AngularModel() {}
|
95
|
+
|
96
|
+
AngularModel.prototype.initialize = function() {
|
97
|
+
var association, clazz, name, obj, _ref, _results;
|
98
|
+
if (this.hasMany) {
|
99
|
+
_ref = this.hasMany;
|
100
|
+
_results = [];
|
101
|
+
for (name in _ref) {
|
102
|
+
clazz = _ref[name];
|
103
|
+
association = this[name] || [];
|
104
|
+
_results.push((function() {
|
105
|
+
var _i, _len, _results2;
|
106
|
+
_results2 = [];
|
107
|
+
for (_i = 0, _len = association.length; _i < _len; _i++) {
|
108
|
+
obj = association[_i];
|
109
|
+
obj.__proto__ = new clazz();
|
110
|
+
_results2.push(typeof obj.initialize === "function" ? obj.initialize() : void 0);
|
111
|
+
}
|
112
|
+
return _results2;
|
113
|
+
})());
|
114
|
+
}
|
115
|
+
return _results;
|
116
|
+
}
|
117
|
+
};
|
118
|
+
|
119
|
+
return AngularModel;
|
120
|
+
|
121
|
+
})();
|
122
|
+
|
123
|
+
angular.service("eventuallyWork", (function($defer) {
|
124
|
+
var eventuallyWork;
|
125
|
+
eventuallyWork = function(func, timeout) {
|
126
|
+
try {
|
127
|
+
return func();
|
128
|
+
} catch (e) {
|
129
|
+
return $defer((function() {
|
130
|
+
return eventuallyWork(func, 2 * timeout);
|
131
|
+
}), timeout);
|
132
|
+
}
|
133
|
+
};
|
134
|
+
return function(func) {
|
135
|
+
return eventuallyWork(func, 10);
|
136
|
+
};
|
137
|
+
}), {
|
138
|
+
$inject: ['$defer']
|
139
|
+
});
|
140
|
+
|
141
|
+
this.autowrap = function(clazz, callback) {
|
142
|
+
return function(result) {
|
143
|
+
result.__proto__ = new clazz();
|
144
|
+
if (typeof result.initialize === "function") result.initialize();
|
145
|
+
if (callback) return callback(result);
|
146
|
+
};
|
147
|
+
};
|
148
|
+
|
149
|
+
}).call(this);
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: angular-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-12-
|
12
|
+
date: 2011-12-17 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &3077880 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.1.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *3077880
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: coffee-script
|
27
|
-
requirement: &
|
27
|
+
requirement: &3077630 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 2.2.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *3077630
|
36
36
|
description: Helpers for angularjs in a rails project (ripped from backbone-rails)
|
37
37
|
email:
|
38
38
|
- nate@ludicast.com
|
@@ -46,7 +46,7 @@ files:
|
|
46
46
|
- lib/generators/angular/controller/templates/controller.coffee
|
47
47
|
- lib/generators/angular/install/install_generator.rb
|
48
48
|
- lib/generators/angular/resource_helpers.rb
|
49
|
-
- vendor/assets/javascripts/
|
49
|
+
- vendor/assets/javascripts/angle-up.js
|
50
50
|
- vendor/assets/javascripts/angular-ie-compat.js
|
51
51
|
- vendor/assets/javascripts/angular.min.js
|
52
52
|
- MIT-LICENSE
|
@@ -89,8 +89,10 @@ files:
|
|
89
89
|
- test/dummy/tmp/cache/assets/CE0/600/sprockets%2F7b3428bf74f80926f20a216683bf5b0f
|
90
90
|
- test/dummy/tmp/cache/assets/D11/830/sprockets%2F376c8de111107498cc89fc305dac169a
|
91
91
|
- test/dummy/tmp/cache/assets/D21/570/sprockets%2Fc943c801ce0caac77ad24200450912ae
|
92
|
+
- test/dummy/tmp/cache/assets/D39/900/sprockets%2Fb8870fba4613fc84863ba75d021a0fb8
|
92
93
|
- test/dummy/tmp/cache/assets/D3C/4A0/sprockets%2F55361a479acf3690d592c04adddfa507
|
93
94
|
- test/dummy/tmp/cache/assets/D9F/120/sprockets%2Fe8a9852102a74db1afd5fe4dd860db93
|
95
|
+
- test/dummy/tmp/cache/assets/D9F/C50/sprockets%2Ff1c6daf537a49ce6c96ef829b3000ad3
|
94
96
|
- test/generators/controller_generator_test.rb
|
95
97
|
- test/generators/fixtures/application.js
|
96
98
|
- test/generators/generators_test_helper.rb
|
@@ -159,8 +161,10 @@ test_files:
|
|
159
161
|
- test/dummy/tmp/cache/assets/CE0/600/sprockets%2F7b3428bf74f80926f20a216683bf5b0f
|
160
162
|
- test/dummy/tmp/cache/assets/D11/830/sprockets%2F376c8de111107498cc89fc305dac169a
|
161
163
|
- test/dummy/tmp/cache/assets/D21/570/sprockets%2Fc943c801ce0caac77ad24200450912ae
|
164
|
+
- test/dummy/tmp/cache/assets/D39/900/sprockets%2Fb8870fba4613fc84863ba75d021a0fb8
|
162
165
|
- test/dummy/tmp/cache/assets/D3C/4A0/sprockets%2F55361a479acf3690d592c04adddfa507
|
163
166
|
- test/dummy/tmp/cache/assets/D9F/120/sprockets%2Fe8a9852102a74db1afd5fe4dd860db93
|
167
|
+
- test/dummy/tmp/cache/assets/D9F/C50/sprockets%2Ff1c6daf537a49ce6c96ef829b3000ad3
|
164
168
|
- test/generators/controller_generator_test.rb
|
165
169
|
- test/generators/fixtures/application.js
|
166
170
|
- test/generators/generators_test_helper.rb
|
@@ -1,62 +0,0 @@
|
|
1
|
-
class @Router
|
2
|
-
initRoutes:(routes)->
|
3
|
-
for routeName, info of routes
|
4
|
-
if routeName is "default"
|
5
|
-
@$route.otherwise redirectTo: info
|
6
|
-
else
|
7
|
-
@$route.when routeName,
|
8
|
-
template: info.template
|
9
|
-
controller: info.controller
|
10
|
-
@$route.parent @
|
11
|
-
|
12
|
-
setupXhr:->
|
13
|
-
@$xhr.defaults.headers.post['Content-Type'] = 'application/json'
|
14
|
-
@$xhr.defaults.headers.put['Content-Type'] = 'application/json'
|
15
|
-
|
16
|
-
token = $("meta[name='csrf-token']").attr("content")
|
17
|
-
@$xhr.defaults.headers.post['X-CSRF-Token'] = token
|
18
|
-
@$xhr.defaults.headers.put['X-CSRF-Token'] = token
|
19
|
-
@$xhr.defaults.headers['delete']['X-CSRF-Token'] = token
|
20
|
-
|
21
|
-
constructor:(@$route, @$xhr)->
|
22
|
-
@setupXhr()
|
23
|
-
@initRoutes @routes()
|
24
|
-
|
25
|
-
@resourceService = (serviceName, path, resourceTypes...)->
|
26
|
-
if resourceTypes.length is 0
|
27
|
-
resourceTypes.push 'index', 'create', 'update', 'destroy', 'show'
|
28
|
-
commandHash = {}
|
29
|
-
for type in resourceTypes
|
30
|
-
commandHash[type] = switch type
|
31
|
-
when 'index'
|
32
|
-
{ method:'GET', isArray:true }
|
33
|
-
when 'show'
|
34
|
-
{ method:'GET', isArray:false }
|
35
|
-
when 'create'
|
36
|
-
{ method: 'POST' }
|
37
|
-
when 'update'
|
38
|
-
{ method: 'PUT' }
|
39
|
-
when 'destroy'
|
40
|
-
{ method: 'DELETE' }
|
41
|
-
|
42
|
-
angular.service serviceName, ($resource)->
|
43
|
-
$resource path, {}, commandHash
|
44
|
-
|
45
|
-
angular.element(document).ready ->
|
46
|
-
angular.compile(document)().$apply()
|
47
|
-
|
48
|
-
class @AngularModel
|
49
|
-
initialize:->
|
50
|
-
if @hasMany
|
51
|
-
for name, clazz of @hasMany
|
52
|
-
association = @[name] or []
|
53
|
-
for obj in association
|
54
|
-
obj.__proto__ = new clazz()
|
55
|
-
obj.initialize?()
|
56
|
-
|
57
|
-
@autowrap = (clazz, callback)->
|
58
|
-
(result)->
|
59
|
-
result.__proto__ = new clazz()
|
60
|
-
result.initialize?()
|
61
|
-
if callback
|
62
|
-
callback(result)
|