mongo_browser 0.2.0.rc2 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. data/.gitignore +3 -1
  2. data/.rspec +1 -1
  3. data/.travis.yml +6 -1
  4. data/CHANGELOG.md +15 -0
  5. data/{grunt.js → Gruntfile.js} +10 -8
  6. data/Procfile +1 -0
  7. data/README.md +44 -2
  8. data/Rakefile +1 -12
  9. data/app/assets/images/ajax-loader.gif +0 -0
  10. data/app/assets/javascripts/app/controllers/{breadcrumbs.js.coffee → breadcrumbs_controller.js.coffee} +4 -7
  11. data/app/assets/javascripts/app/controllers/collections/index_controller.js.coffee +38 -0
  12. data/app/assets/javascripts/app/controllers/collections/stats_controller.js.coffee +17 -0
  13. data/app/assets/javascripts/app/controllers/{databases.js.coffee → databases/index_controller.js.coffee} +11 -15
  14. data/app/assets/javascripts/app/controllers/databases/stats_controller.js.coffee +15 -0
  15. data/app/assets/javascripts/app/controllers/documents/index_controller.js.coffee +54 -0
  16. data/app/assets/javascripts/app/controllers/documents/show_controller.js.coffee +38 -0
  17. data/app/assets/javascripts/app/controllers/main_controller.js.coffee +15 -0
  18. data/app/assets/javascripts/app/controllers/servers/show_controller.js.coffee +17 -0
  19. data/app/assets/javascripts/app/directives.js.coffee +23 -0
  20. data/app/assets/javascripts/app/filters.js.coffee +14 -1
  21. data/app/assets/javascripts/app/modules/alerts.js.coffee +58 -0
  22. data/app/assets/javascripts/app/modules/pager.js.coffee +2 -2
  23. data/app/assets/javascripts/app/modules/spinner.js.coffee +29 -0
  24. data/app/assets/javascripts/app/modules/table_filter.js.coffee +4 -4
  25. data/app/assets/javascripts/app/resources.js.coffee +14 -8
  26. data/app/assets/javascripts/app/services.js.coffee +11 -33
  27. data/app/assets/javascripts/application.js.coffee +62 -34
  28. data/app/assets/javascripts/application.test.js.coffee +5 -0
  29. data/app/assets/javascripts/compiled_templates.js.coffee +1 -0
  30. data/app/assets/javascripts/vendor.js.coffee +0 -1
  31. data/app/assets/stylesheets/application.css.scss +36 -18
  32. data/{public/index.html → app/views/index.erb} +8 -8
  33. data/bin/mongo_browser +2 -13
  34. data/config.ru +3 -1
  35. data/lib/mongo_browser.rb +1 -0
  36. data/lib/mongo_browser/api.rb +11 -0
  37. data/lib/mongo_browser/api/collections.rb +34 -0
  38. data/lib/mongo_browser/api/databases.rb +32 -0
  39. data/lib/mongo_browser/api/documents.rb +37 -0
  40. data/lib/mongo_browser/api/mongo.rb +41 -0
  41. data/lib/mongo_browser/application.rb +8 -174
  42. data/lib/mongo_browser/application/development.rb +32 -0
  43. data/lib/mongo_browser/cli.rb +48 -0
  44. data/lib/mongo_browser/entities.rb +43 -0
  45. data/lib/mongo_browser/models/collection.rb +7 -12
  46. data/lib/mongo_browser/models/document.rb +5 -1
  47. data/lib/mongo_browser/models/pager.rb +22 -9
  48. data/lib/mongo_browser/version.rb +1 -1
  49. data/mongo_browser.gemspec +22 -15
  50. data/package.json +30 -0
  51. data/public/ng/templates/alerts.html +6 -0
  52. data/public/ng/templates/collections/index.html +39 -0
  53. data/public/ng/templates/collections/stats.html +18 -0
  54. data/public/ng/templates/databases/index.html +35 -0
  55. data/public/ng/templates/databases/stats.html +18 -0
  56. data/public/ng/templates/documents/index.html +40 -0
  57. data/public/ng/templates/documents/show.html +17 -0
  58. data/{app/assets → public/ng}/templates/pager.html +0 -0
  59. data/{app/assets/templates/server_info.html → public/ng/templates/server/show.html} +1 -1
  60. data/{app/assets → public/ng}/templates/table_filter.html +0 -0
  61. data/script/ci_all +5 -1
  62. data/script/ci_e2e +5 -2
  63. data/script/ci_javascripts +1 -1
  64. data/script/ci_rspec +1 -1
  65. data/spec/javascripts/app/controllers/{breadcrumbs_spec.js.coffee → breadcrumbs_controller_spec.js.coffee} +1 -1
  66. data/spec/javascripts/app/controllers/collections/index_controller_spec.js.coffee +95 -0
  67. data/spec/javascripts/app/controllers/collections/stats_controller_spec.js.coffee +34 -0
  68. data/spec/javascripts/app/controllers/databases/index_controller_spec.js.coffee +93 -0
  69. data/spec/javascripts/app/controllers/databases/stats_controller_spec.js.coffee +30 -0
  70. data/spec/javascripts/app/controllers/documents/index_controller_spec.js.coffee +108 -0
  71. data/spec/javascripts/app/controllers/documents/show_controller_spec.js.coffee +94 -0
  72. data/spec/javascripts/app/controllers/{main_spec.js.coffee → main_controller_spec.js.coffee} +2 -2
  73. data/spec/javascripts/app/controllers/{server_info_spec.js.coffee → server/show_controller_spec.js.coffee} +5 -6
  74. data/spec/javascripts/app/directives_spec.js.coffee +108 -24
  75. data/spec/javascripts/app/filters_spec.js.coffee +31 -5
  76. data/spec/javascripts/app/modules/alerts_spec.js.coffee +138 -0
  77. data/spec/javascripts/app/modules/dialogs_spec.js.coffee +1 -2
  78. data/spec/javascripts/app/modules/pager_spec.js.coffee +0 -1
  79. data/spec/javascripts/app/modules/spinner_spec.js.coffee +65 -0
  80. data/spec/javascripts/app/modules/table_filter_spec.js.coffee +9 -9
  81. data/spec/javascripts/app/resources_spec.js.coffee +99 -0
  82. data/spec/javascripts/app/services_spec.js.coffee +31 -71
  83. data/spec/javascripts/config/{testacular-e2e.conf.js → karma-e2e.conf.js} +1 -1
  84. data/spec/javascripts/config/{testacular.conf.js → karma.conf.js} +2 -3
  85. data/spec/javascripts/e2e/collection_stats_scenario.js.coffee +12 -0
  86. data/spec/javascripts/e2e/collections_scenario.js.coffee +59 -20
  87. data/spec/javascripts/e2e/database_stats_scenario.js.coffee +11 -0
  88. data/spec/javascripts/e2e/databases_scenario.js.coffee +37 -36
  89. data/spec/javascripts/e2e/document_show_scenario.js.coffee +31 -0
  90. data/spec/javascripts/e2e/documents_pagination_scenario.js.coffee +33 -0
  91. data/spec/javascripts/e2e/documents_scenario.js.coffee +43 -4
  92. data/spec/javascripts/e2e/server_info_scenario.js.coffee +8 -2
  93. data/spec/javascripts/helpers/mocks.js.coffee +2 -0
  94. data/spec/javascripts/helpers_e2e/dsl.js.coffee +20 -0
  95. data/spec/javascripts/lib/angular-mocks.js +64 -16
  96. data/spec/javascripts/lib/angular-scenario.js +724 -561
  97. data/spec/javascripts/runner.html +5 -5
  98. data/spec/lib/api/collections_spec.rb +62 -0
  99. data/spec/lib/api/databases_spec.rb +58 -0
  100. data/spec/lib/api/documents_spec.rb +135 -0
  101. data/spec/lib/api/mongo_spec.rb +27 -0
  102. data/spec/lib/cli_spec.rb +19 -0
  103. data/spec/lib/entities_spec.rb +39 -0
  104. data/spec/lib/models/collection_spec.rb +16 -10
  105. data/spec/lib/models/database_spec.rb +4 -4
  106. data/spec/lib/models/document_spec.rb +5 -5
  107. data/spec/lib/models/pager_spec.rb +20 -11
  108. data/spec/spec_helper.rb +7 -15
  109. data/spec/support/api_example_group.rb +45 -0
  110. data/spec/support/fixtures.rb +10 -6
  111. data/spec/support/matchers/expose.rb +18 -0
  112. data/vendor/assets/javascripts/angular/angular-bootstrap.js +1 -1
  113. data/vendor/assets/javascripts/angular/angular-resource.js +78 -56
  114. data/vendor/assets/javascripts/angular/angular-sanitize.js +3 -1
  115. data/vendor/assets/javascripts/angular/angular.js +720 -404
  116. metadata +323 -183
  117. data/app/assets/javascripts/app.js.coffee +0 -8
  118. data/app/assets/javascripts/app/controllers.js.coffee +0 -2
  119. data/app/assets/javascripts/app/controllers/alerts.js.coffee +0 -12
  120. data/app/assets/javascripts/app/controllers/collections.js.coffee +0 -40
  121. data/app/assets/javascripts/app/controllers/documents.js.coffee +0 -49
  122. data/app/assets/javascripts/app/controllers/main.js.coffee +0 -10
  123. data/app/assets/javascripts/app/controllers/server_info.js.coffee +0 -14
  124. data/app/assets/javascripts/templates.js.coffee +0 -1
  125. data/app/assets/javascripts/templates/.gitkeep +0 -0
  126. data/app/assets/templates/collections.html +0 -53
  127. data/app/assets/templates/databases.html +0 -32
  128. data/app/assets/templates/documents.html +0 -45
  129. data/config-e2e.ru +0 -20
  130. data/spec/features/collections_list_spec.rb +0 -64
  131. data/spec/features/documents_list_spec.rb +0 -139
  132. data/spec/features/server_info_spec.rb +0 -23
  133. data/spec/javascripts/app/controllers/alerts_spec.js.coffee +0 -36
  134. data/spec/javascripts/app/controllers/collections_spec.js.coffee +0 -78
  135. data/spec/javascripts/app/controllers/databases_spec.js.coffee +0 -55
  136. data/spec/javascripts/app/controllers/documents_spec.js.coffee +0 -62
  137. data/spec/javascripts/helpers_e2e/app_element.js.coffee +0 -6
  138. data/spec/support/feature_example_group.rb +0 -53
  139. data/spec/support/matchers/have_flash_message.rb +0 -16
  140. data/spec/support/mongod.rb +0 -91
  141. data/spec/support/mongodb.conf +0 -47
@@ -1,14 +1,14 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe MongoBrowser::Models::Document do
4
- let(:mongo_db_name) { "first_database" }
5
- let(:mongo_collection_name) { "first_collection" }
4
+ let(:db_name) { "first_database" }
5
+ let(:collection_name) { "first_collection" }
6
6
 
7
7
  let(:server) { MongoBrowser::Models::Server.current }
8
- let(:mongo_collection) { server.connection[mongo_db_name].collection(mongo_collection_name) }
9
- let(:mongo_document) { mongo_collection.find.first }
8
+ let(:colleciton) { server.connection[db_name].collection(collection_name) }
9
+ let(:mongo_document) { colleciton.find.first }
10
10
 
11
- let(:document) { described_class.new(mongo_document) }
11
+ let(:document) { described_class.new(db_name, collection_name, mongo_document) }
12
12
  subject { document }
13
13
 
14
14
  its(:id) { should_not be_nil }
@@ -1,49 +1,49 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe MongoBrowser::Models::Pager do
4
- let(:current_page) { 1 }
4
+ let(:page) { 1 }
5
5
  let(:size) { 25 }
6
6
 
7
- let(:pager) { described_class.new(current_page, size) }
7
+ let(:pager) { described_class.new(page, size) }
8
8
  subject { pager }
9
9
 
10
10
  before { pager.stub(:per_page).and_return(25) }
11
11
 
12
- describe "#current_page" do
13
- subject { pager.current_page }
12
+ describe "#page" do
13
+ subject { pager.page }
14
14
 
15
15
  [-2, -1, 0, 1].each do |number|
16
16
  context "when the given page number is #{number}" do
17
- let(:current_page) { number }
17
+ let(:page) { number }
18
18
 
19
19
  it("return the first page") { should == 1 }
20
20
  end
21
21
  end
22
22
 
23
23
  context "when the given page number exceed the total pages number" do
24
- let(:current_page) { 3 }
24
+ let(:page) { 3 }
25
25
  let(:size) { 30 }
26
26
 
27
27
  it("returns the last page number") { should == 2 }
28
28
  end
29
29
 
30
30
  context "otherwise" do
31
- let(:current_page) { 2 }
31
+ let(:page) { 2 }
32
32
  let(:size) { 26 }
33
33
 
34
- it("returns the current page") { should == current_page }
34
+ it("returns the current page") { should == page }
35
35
  end
36
36
  end
37
37
 
38
38
  describe "#offset" do
39
39
  subject { pager.offset }
40
40
 
41
- context "when current_page eq 1" do
41
+ context "when page eq 1" do
42
42
  it { should == 0 }
43
43
  end
44
44
 
45
45
  context "otherwise" do
46
- let(:current_page) { 2 }
46
+ let(:page) { 2 }
47
47
  let(:size) { 26 }
48
48
 
49
49
  it("return a valid offset") { should == 25 }
@@ -53,7 +53,7 @@ describe MongoBrowser::Models::Pager do
53
53
  describe "#total_pages" do
54
54
  subject { pager.total_pages }
55
55
 
56
- { 1 => 1, 25 => 1, 26 => 2, 50 => 2, 51 => 3, 101 => 5 }.each do |size, expected|
56
+ { 0 => 1, 1 => 1, 25 => 1, 26 => 2, 50 => 2, 51 => 3, 101 => 5 }.each do |size, expected|
57
57
  context "when the size is #{size}" do
58
58
  let(:size) { size }
59
59
 
@@ -61,4 +61,13 @@ describe MongoBrowser::Models::Pager do
61
61
  end
62
62
  end
63
63
  end
64
+
65
+ describe "#to_hash" do
66
+ subject { pager.to_hash }
67
+
68
+ it { should be_an_instance_of(Hash) }
69
+ its([:size]) { should == 25 }
70
+ its([:page]) { should == 1 }
71
+ its([:total_pages]) { should == 1 }
72
+ end
64
73
  end
@@ -4,28 +4,20 @@ require "mongo_browser"
4
4
 
5
5
  require "debugger"
6
6
  require "rspec"
7
+ require "rack/test"
8
+
9
+ if ENV["TRAVIS"]
10
+ require "coveralls"
11
+ Coveralls.wear!
12
+ end
7
13
 
8
14
  # Requires supporting ruby files with custom matchers and macros, etc,
9
15
  # from spec/support/ and its subdirectories.
10
16
  Dir[File.expand_path("spec/support/**/*.rb")].each { |f| require f }
11
17
 
12
- test_server = Mongod.instance
13
- fixtures = Fixtures.instance
14
-
15
18
  RSpec.configure do |config|
16
- config.include FeatureExampleGroup, type: :request
17
-
18
- # Run test mongod instance and load database fixtures
19
19
  config.before do
20
- test_server.start! do |port|
21
- MongoBrowser.mongodb_host = "127.0.0.1"
22
- MongoBrowser.mongodb_port = port
23
- end
24
-
20
+ fixtures = Fixtures.instance
25
21
  fixtures.load!
26
22
  end
27
23
  end
28
-
29
- at_exit do
30
- test_server.shutdown!
31
- end
@@ -0,0 +1,45 @@
1
+ module ApiExampleGroup
2
+ include Rack::Test::Methods
3
+
4
+ def self.included(base)
5
+ base.let(:server) { MongoBrowser::Models::Server.current }
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ # Helper for describing API endpoints
11
+ #
12
+ # Usage:
13
+ # describe_endpoint :delete, "/databases/:db_name" do
14
+ # let(:db_name) { "first_database" }
15
+ # # some assertions here
16
+ # end
17
+ def describe_endpoint(method, route_path, &block)
18
+ describe "#{method.upcase} #{route_path}" do
19
+ let(:path) do
20
+ path = route_path.clone
21
+ route_path.scan(/(:(\w+))/).each do |place_holder, name|
22
+ path.sub!(place_holder, instance_eval(name).to_s)
23
+ end
24
+
25
+ path
26
+ end
27
+
28
+ let(:do_request) { send(method.downcase.to_sym, path) }
29
+ subject(:response) { do_request }
30
+
31
+ # Create a new context with route description
32
+ by_path = -> route { route.route_path.match(/^#{route_path.split("?").first}/) }
33
+ route = described_class.routes.find(&by_path)
34
+
35
+ if route and route.route_description
36
+ describe route.route_description do
37
+ instance_eval(&block)
38
+ end
39
+ else
40
+ instance_eval(&block)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -20,16 +20,20 @@ class Fixtures
20
20
  end
21
21
  end
22
22
 
23
+ def load_documents!
24
+ database = connection.db("first_database")
25
+ collection = database.collection("second_collection")
26
+ collection.remove()
27
+
28
+ 70.times do |n|
29
+ collection.insert(name: "Document #{n}", position: n)
30
+ end
31
+ end
32
+
23
33
  # Delete all databases
24
34
  def cleanup!
25
35
  fixture_databases = data.map { |db| db["name"] }
26
36
 
27
- # Drop all databases outside fixtures
28
- other_databases = connection.database_names - fixture_databases
29
- other_databases.each do |db_name|
30
- connection.drop_database(db_name)
31
- end
32
-
33
37
  # Drop collections inside databases
34
38
  fixture_databases.each do |db_name|
35
39
  collection_names = connection[db_name].collection_names - ["system.indexes"]
@@ -0,0 +1,18 @@
1
+ RSpec::Matchers.define :expose do |expected|
2
+ match do |entity|
3
+ entity.exposures.keys.include?(expected)
4
+ end
5
+
6
+ failure_message_for_should do |entity|
7
+ "expected that #{entity} would exposure :#{expected}"
8
+ end
9
+
10
+ description do |entity|
11
+ str = "expose :#{expected}"
12
+
13
+ doc = entity.documentation[expected]
14
+ str << " [#{doc[:type]}] #{doc[:desc]}" if doc
15
+
16
+ str
17
+ end
18
+ end
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.1.1
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.7
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -12,7 +12,7 @@
12
12
  * @description
13
13
  */
14
14
 
15
- /**
15
+ /**
16
16
  * @ngdoc object
17
17
  * @name ngResource.$resource
18
18
  * @requires $http
@@ -24,8 +24,21 @@
24
24
  * The returned resource object has action methods which provide high-level behaviors without
25
25
  * the need to interact with the low level {@link ng.$http $http} service.
26
26
  *
27
+ * # Installation
28
+ * To use $resource make sure you have included the `angular-resource.js` that comes in Angular
29
+ * package. You can also find this file on Google CDN, bower as well as at
30
+ * {@link http://code.angularjs.org/ code.angularjs.org}.
31
+ *
32
+ * Finally load the module in your application:
33
+ *
34
+ * angular.module('app', ['ngResource']);
35
+ *
36
+ * and you are ready to get started!
37
+ *
27
38
  * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
28
- * `/user/:username`.
39
+ * `/user/:username`. If you are using a URL with a port number (e.g.
40
+ * `http://example.com:8080/api`), you'll need to escape the colon character before the port
41
+ * number, like this: `$resource('http://example.com\\:8080/api')`.
29
42
  *
30
43
  * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
31
44
  * `actions` methods.
@@ -67,9 +80,9 @@
67
80
  *
68
81
  * Calling these methods invoke an {@link ng.$http} with the specified http method,
69
82
  * destination and parameters. When the data is returned from the server then the object is an
70
- * instance of the resource class `save`, `remove` and `delete` actions are available on it as
71
- * methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,
72
- * update, delete) on server-side data like this:
83
+ * instance of the resource class. The actions `save`, `remove` and `delete` are available on it
84
+ * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
85
+ * read, update, delete) on server-side data like this:
73
86
  * <pre>
74
87
  var User = $resource('/user/:userId', {userId:'@id'});
75
88
  var user = User.get({userId:123}, function() {
@@ -149,9 +162,9 @@
149
162
  });
150
163
  </pre>
151
164
  *
152
- * It's worth noting that the success callback for `get`, `query` and other method gets passed
153
- * in the response that came from the server as well as $http header getter function, so one
154
- * could rewrite the above example and get access to http headers as:
165
+ * It's worth noting that the success callback for `get`, `query` and other method gets passed
166
+ * in the response that came from the server as well as $http header getter function, so one
167
+ * could rewrite the above example and get access to http headers as:
155
168
  *
156
169
  <pre>
157
170
  var User = $resource('/user/:userId', {userId:'@id'});
@@ -230,51 +243,51 @@ angular.module('ngResource', ['ng']).
230
243
  return $parse(path)(obj);
231
244
  };
232
245
 
233
- /**
234
- * We need our custom mehtod because encodeURIComponent is too aggressive and doesn't follow
235
- * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
236
- * segments:
237
- * segment = *pchar
238
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
239
- * pct-encoded = "%" HEXDIG HEXDIG
240
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
241
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
242
- * / "*" / "+" / "," / ";" / "="
243
- */
244
- function encodeUriSegment(val) {
245
- return encodeUriQuery(val, true).
246
- replace(/%26/gi, '&').
247
- replace(/%3D/gi, '=').
248
- replace(/%2B/gi, '+');
249
- }
250
-
251
-
252
- /**
253
- * This method is intended for encoding *key* or *value* parts of query component. We need a custom
254
- * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
255
- * encoded per http://tools.ietf.org/html/rfc3986:
256
- * query = *( pchar / "/" / "?" )
257
- * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
258
- * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
259
- * pct-encoded = "%" HEXDIG HEXDIG
260
- * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
261
- * / "*" / "+" / "," / ";" / "="
262
- */
263
- function encodeUriQuery(val, pctEncodeSpaces) {
264
- return encodeURIComponent(val).
265
- replace(/%40/gi, '@').
266
- replace(/%3A/gi, ':').
267
- replace(/%24/g, '$').
268
- replace(/%2C/gi, ',').
269
- replace((pctEncodeSpaces ? null : /%20/g), '+');
270
- }
271
-
272
- function Route(template, defaults) {
246
+ /**
247
+ * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
248
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
249
+ * segments:
250
+ * segment = *pchar
251
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
252
+ * pct-encoded = "%" HEXDIG HEXDIG
253
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
254
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
255
+ * / "*" / "+" / "," / ";" / "="
256
+ */
257
+ function encodeUriSegment(val) {
258
+ return encodeUriQuery(val, true).
259
+ replace(/%26/gi, '&').
260
+ replace(/%3D/gi, '=').
261
+ replace(/%2B/gi, '+');
262
+ }
263
+
264
+
265
+ /**
266
+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
267
+ * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
268
+ * encoded per http://tools.ietf.org/html/rfc3986:
269
+ * query = *( pchar / "/" / "?" )
270
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
271
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
272
+ * pct-encoded = "%" HEXDIG HEXDIG
273
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
274
+ * / "*" / "+" / "," / ";" / "="
275
+ */
276
+ function encodeUriQuery(val, pctEncodeSpaces) {
277
+ return encodeURIComponent(val).
278
+ replace(/%40/gi, '@').
279
+ replace(/%3A/gi, ':').
280
+ replace(/%24/g, '$').
281
+ replace(/%2C/gi, ',').
282
+ replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
283
+ }
284
+
285
+ function Route(template, defaults) {
273
286
  this.template = template = template + '#';
274
287
  this.defaults = defaults || {};
275
288
  var urlParams = this.urlParams = {};
276
289
  forEach(template.split(/\W/), function(param){
277
- if (param && template.match(new RegExp("[^\\\\]:" + param + "\\W"))) {
290
+ if (param && (new RegExp("(^|[^\\\\]):" + param + "\\W").test(template))) {
278
291
  urlParams[param] = true;
279
292
  }
280
293
  });
@@ -295,7 +308,14 @@ angular.module('ngResource', ['ng']).
295
308
  encodedVal = encodeUriSegment(val);
296
309
  url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
297
310
  } else {
298
- url = url.replace(new RegExp("/?:" + urlParam + "(\\W)", "g"), '$1');
311
+ url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match,
312
+ leadingSlashes, tail) {
313
+ if (tail.charAt(0) == '/') {
314
+ return tail;
315
+ } else {
316
+ return leadingSlashes + tail;
317
+ }
318
+ });
299
319
  }
300
320
  });
301
321
  url = url.replace(/\/?#$/, '');
@@ -331,6 +351,7 @@ angular.module('ngResource', ['ng']).
331
351
  }
332
352
 
333
353
  forEach(actions, function(action, name) {
354
+ action.method = angular.uppercase(action.method);
334
355
  var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';
335
356
  Resource[name] = function(a1, a2, a3, a4) {
336
357
  var params = {};
@@ -396,11 +417,6 @@ angular.module('ngResource', ['ng']).
396
417
  };
397
418
 
398
419
 
399
- Resource.bind = function(additionalParamDefaults){
400
- return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
401
- };
402
-
403
-
404
420
  Resource.prototype['$' + name] = function(a1, a2, a3) {
405
421
  var params = extractParams(this),
406
422
  success = noop,
@@ -426,10 +442,16 @@ angular.module('ngResource', ['ng']).
426
442
  Resource[name].call(this, params, data, success, error);
427
443
  };
428
444
  });
445
+
446
+ Resource.bind = function(additionalParamDefaults){
447
+ return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
448
+ };
449
+
429
450
  return Resource;
430
451
  }
431
452
 
432
453
  return ResourceFactory;
433
454
  }]);
434
455
 
456
+
435
457
  })(window, window.angular);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.3
2
+ * @license AngularJS v1.0.7
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -422,6 +422,7 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
422
422
  });
423
423
  };
424
424
  }]);
425
+
425
426
  /**
426
427
  * @ngdoc filter
427
428
  * @name ngSanitize.filter:linky
@@ -532,4 +533,5 @@ angular.module('ngSanitize').filter('linky', function() {
532
533
  };
533
534
  });
534
535
 
536
+
535
537
  })(window, window.angular);