extjs_renderer 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/.gitignore +8 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +112 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +63 -0
  7. data/Rakefile +25 -0
  8. data/extjs_renderer.gemspec +26 -0
  9. data/lib/extjs_renderer/renderer.rb +31 -0
  10. data/lib/extjs_renderer/version.rb +3 -0
  11. data/lib/extjs_renderer.rb +2 -0
  12. data/spec/dummy/Rakefile +7 -0
  13. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  14. data/spec/dummy/app/controllers/items_controller.rb +17 -0
  15. data/spec/dummy/app/controllers/orders_controller.rb +115 -0
  16. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  17. data/spec/dummy/app/helpers/orders_helper.rb +2 -0
  18. data/spec/dummy/app/models/item.rb +8 -0
  19. data/spec/dummy/app/models/order.rb +10 -0
  20. data/spec/dummy/app/views/items/index.html.erb +2 -0
  21. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  22. data/spec/dummy/app/views/orders/index.html.erb +2 -0
  23. data/spec/dummy/config/application.rb +48 -0
  24. data/spec/dummy/config/boot.rb +10 -0
  25. data/spec/dummy/config/database.yml +22 -0
  26. data/spec/dummy/config/environment.rb +5 -0
  27. data/spec/dummy/config/environments/development.rb +26 -0
  28. data/spec/dummy/config/environments/production.rb +49 -0
  29. data/spec/dummy/config/environments/test.rb +35 -0
  30. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  31. data/spec/dummy/config/initializers/inflections.rb +10 -0
  32. data/spec/dummy/config/initializers/json.rb +1 -0
  33. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  34. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  35. data/spec/dummy/config/initializers/session_store.rb +8 -0
  36. data/spec/dummy/config/locales/en.yml +5 -0
  37. data/spec/dummy/config/routes.rb +79 -0
  38. data/spec/dummy/config.ru +4 -0
  39. data/spec/dummy/db/migrate/20111116202653_create_orders.rb +13 -0
  40. data/spec/dummy/db/migrate/20111116202739_create_items.rb +14 -0
  41. data/spec/dummy/public/404.html +26 -0
  42. data/spec/dummy/public/422.html +26 -0
  43. data/spec/dummy/public/500.html +26 -0
  44. data/spec/dummy/public/favicon.ico +0 -0
  45. data/spec/dummy/public/javascripts/application.js +2 -0
  46. data/spec/dummy/public/javascripts/controls.js +965 -0
  47. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  48. data/spec/dummy/public/javascripts/effects.js +1123 -0
  49. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  50. data/spec/dummy/public/javascripts/rails.js +191 -0
  51. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  52. data/spec/dummy/script/rails +6 -0
  53. data/spec/dummy/spec/controllers/items_controller_spec.rb +42 -0
  54. data/spec/dummy/spec/controllers/orders_controller_spec.rb +216 -0
  55. data/spec/dummy/spec/models/order_spec.rb +24 -0
  56. data/spec/extjs_renderer_spec.rb +7 -0
  57. data/spec/spec_helper.rb +24 -0
  58. data/spec/support/factories.rb +14 -0
  59. metadata +199 -0
@@ -0,0 +1,191 @@
1
+ (function() {
2
+ // Technique from Juriy Zaytsev
3
+ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
4
+ function isEventSupported(eventName) {
5
+ var el = document.createElement('div');
6
+ eventName = 'on' + eventName;
7
+ var isSupported = (eventName in el);
8
+ if (!isSupported) {
9
+ el.setAttribute(eventName, 'return;');
10
+ isSupported = typeof el[eventName] == 'function';
11
+ }
12
+ el = null;
13
+ return isSupported;
14
+ }
15
+
16
+ function isForm(element) {
17
+ return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'
18
+ }
19
+
20
+ function isInput(element) {
21
+ if (Object.isElement(element)) {
22
+ var name = element.nodeName.toUpperCase()
23
+ return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'
24
+ }
25
+ else return false
26
+ }
27
+
28
+ var submitBubbles = isEventSupported('submit'),
29
+ changeBubbles = isEventSupported('change')
30
+
31
+ if (!submitBubbles || !changeBubbles) {
32
+ // augment the Event.Handler class to observe custom events when needed
33
+ Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
34
+ function(init, element, eventName, selector, callback) {
35
+ init(element, eventName, selector, callback)
36
+ // is the handler being attached to an element that doesn't support this event?
37
+ if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
38
+ (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
39
+ // "submit" => "emulated:submit"
40
+ this.eventName = 'emulated:' + this.eventName
41
+ }
42
+ }
43
+ )
44
+ }
45
+
46
+ if (!submitBubbles) {
47
+ // discover forms on the page by observing focus events which always bubble
48
+ document.on('focusin', 'form', function(focusEvent, form) {
49
+ // special handler for the real "submit" event (one-time operation)
50
+ if (!form.retrieve('emulated:submit')) {
51
+ form.on('submit', function(submitEvent) {
52
+ var emulated = form.fire('emulated:submit', submitEvent, true)
53
+ // if custom event received preventDefault, cancel the real one too
54
+ if (emulated.returnValue === false) submitEvent.preventDefault()
55
+ })
56
+ form.store('emulated:submit', true)
57
+ }
58
+ })
59
+ }
60
+
61
+ if (!changeBubbles) {
62
+ // discover form inputs on the page
63
+ document.on('focusin', 'input, select, texarea', function(focusEvent, input) {
64
+ // special handler for real "change" events
65
+ if (!input.retrieve('emulated:change')) {
66
+ input.on('change', function(changeEvent) {
67
+ input.fire('emulated:change', changeEvent, true)
68
+ })
69
+ input.store('emulated:change', true)
70
+ }
71
+ })
72
+ }
73
+
74
+ function handleRemote(element) {
75
+ var method, url, params;
76
+
77
+ var event = element.fire("ajax:before");
78
+ if (event.stopped) return false;
79
+
80
+ if (element.tagName.toLowerCase() === 'form') {
81
+ method = element.readAttribute('method') || 'post';
82
+ url = element.readAttribute('action');
83
+ params = element.serialize();
84
+ } else {
85
+ method = element.readAttribute('data-method') || 'get';
86
+ url = element.readAttribute('href');
87
+ params = {};
88
+ }
89
+
90
+ new Ajax.Request(url, {
91
+ method: method,
92
+ parameters: params,
93
+ evalScripts: true,
94
+
95
+ onComplete: function(request) { element.fire("ajax:complete", request); },
96
+ onSuccess: function(request) { element.fire("ajax:success", request); },
97
+ onFailure: function(request) { element.fire("ajax:failure", request); }
98
+ });
99
+
100
+ element.fire("ajax:after");
101
+ }
102
+
103
+ function handleMethod(element) {
104
+ var method = element.readAttribute('data-method'),
105
+ url = element.readAttribute('href'),
106
+ csrf_param = $$('meta[name=csrf-param]')[0],
107
+ csrf_token = $$('meta[name=csrf-token]')[0];
108
+
109
+ var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
110
+ element.parentNode.insert(form);
111
+
112
+ if (method !== 'post') {
113
+ var field = new Element('input', { type: 'hidden', name: '_method', value: method });
114
+ form.insert(field);
115
+ }
116
+
117
+ if (csrf_param) {
118
+ var param = csrf_param.readAttribute('content'),
119
+ token = csrf_token.readAttribute('content'),
120
+ field = new Element('input', { type: 'hidden', name: param, value: token });
121
+ form.insert(field);
122
+ }
123
+
124
+ form.submit();
125
+ }
126
+
127
+
128
+ document.on("click", "*[data-confirm]", function(event, element) {
129
+ var message = element.readAttribute('data-confirm');
130
+ if (!confirm(message)) event.stop();
131
+ });
132
+
133
+ document.on("click", "a[data-remote]", function(event, element) {
134
+ if (event.stopped) return;
135
+ handleRemote(element);
136
+ event.stop();
137
+ });
138
+
139
+ document.on("click", "a[data-method]", function(event, element) {
140
+ if (event.stopped) return;
141
+ handleMethod(element);
142
+ event.stop();
143
+ });
144
+
145
+ document.on("submit", function(event) {
146
+ var element = event.findElement(),
147
+ message = element.readAttribute('data-confirm');
148
+ if (message && !confirm(message)) {
149
+ event.stop();
150
+ return false;
151
+ }
152
+
153
+ var inputs = element.select("input[type=submit][data-disable-with]");
154
+ inputs.each(function(input) {
155
+ input.disabled = true;
156
+ input.writeAttribute('data-original-value', input.value);
157
+ input.value = input.readAttribute('data-disable-with');
158
+ });
159
+
160
+ var element = event.findElement("form[data-remote]");
161
+ if (element) {
162
+ handleRemote(element);
163
+ event.stop();
164
+ }
165
+ });
166
+
167
+ document.on("ajax:after", "form", function(event, element) {
168
+ var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
169
+ inputs.each(function(input) {
170
+ input.value = input.readAttribute('data-original-value');
171
+ input.removeAttribute('data-original-value');
172
+ input.disabled = false;
173
+ });
174
+ });
175
+
176
+ Ajax.Responders.register({
177
+ onCreate: function(request) {
178
+ var csrf_meta_tag = $$('meta[name=csrf-token]')[0];
179
+
180
+ if (csrf_meta_tag) {
181
+ var header = 'X-CSRF-Token',
182
+ token = csrf_meta_tag.readAttribute('content');
183
+
184
+ if (!request.options.requestHeaders) {
185
+ request.options.requestHeaders = {};
186
+ }
187
+ request.options.requestHeaders[header] = token;
188
+ }
189
+ }
190
+ });
191
+ })();
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe ItemsController do
4
+ describe "GET 'index'" do
5
+ it "returns http success" do
6
+ get 'index'
7
+ response.should be_success
8
+ end
9
+
10
+ it "responds to xhr with formatted json" do
11
+ 2.times{|n| Factory.create(:item) }
12
+ xhr :get, :index, :format => :json
13
+ json = ActiveSupport::JSON.decode(response.body)
14
+ json['total'].should eq(2)
15
+ json['item'].should_not be_nil
16
+ end
17
+
18
+ it "processes overridden as_json" do
19
+ 2.times{|n| Factory.create(:item) }
20
+ xhr :get, :index, :format => :json
21
+ json = ActiveSupport::JSON.decode(response.body)
22
+ json['item'].each do |item|
23
+ item['name'].should_not be_nil
24
+ item['created_at'].should be_nil
25
+ item['updated_at'].should be_nil
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "GET 'edit'" do
31
+ it "processes overridden as_json" do
32
+ item = Factory.create(:item)
33
+ xhr :get, :edit, :id => item.id, :format => :json
34
+ json = ActiveSupport::JSON.decode(response.body)
35
+ json['data'].should_not be_nil
36
+ json['data']['id'].should eq(item.id)
37
+ json['data']['name'].should eq(item.name)
38
+ json['data']['created_at'].should be_nil
39
+ json['data']['updated_at'].should be_nil
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,216 @@
1
+ require 'spec_helper'
2
+
3
+ describe OrdersController do
4
+
5
+ context "ActiveRecord Relation" do
6
+
7
+ describe "GET 'index'" do
8
+ it "returns http success" do
9
+ get 'index'
10
+ response.should be_success
11
+ end
12
+
13
+ it "responds to xhr with formatted json" do
14
+ Factory.create(:order)
15
+ xhr :get, :index, :format => :json
16
+ json = ActiveSupport::JSON.decode(response.body)
17
+ json['total'].should eq(1)
18
+ json['order'].should_not be_nil
19
+ end
20
+ end
21
+
22
+ describe "GET 'change_root'" do
23
+ it "responds to xhr with user passed root" do
24
+ Factory.create(:order)
25
+ xhr :get, :change_root, :format => :json
26
+ json = ActiveSupport::JSON.decode(response.body)
27
+ json['total'].should eq(1)
28
+ json['order'].should be_nil # root should be changed
29
+ json['custom_root'].should_not be_nil # to user passed root
30
+ end
31
+ end
32
+
33
+ describe "GET 'change_total'" do
34
+ it "responds to xhr with user passed total" do
35
+ Factory.create(:order)
36
+ xhr :get, :change_total, :format => :json
37
+ json = ActiveSupport::JSON.decode(response.body)
38
+ json['total'].should eq(34)
39
+ end
40
+ end
41
+
42
+ describe "GET 'with_method'" do
43
+ it "responds to xhr with user passed total, root, and method" do
44
+ Factory.create(:order)
45
+ xhr :get, :with_method, :format => :json
46
+ json = ActiveSupport::JSON.decode(response.body)
47
+ json['total'].should eq(34)
48
+ json['order'].should be_nil # root should be changed
49
+ json['custom_root'].should_not be_nil # to user passed root
50
+ json['custom_root'].each do |order|
51
+ order['custom'].should_not be_nil
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "GET 'only_and_method'" do
57
+ it "responds to xhr with user passed total, root, and method" do
58
+ Factory.create(:order)
59
+ xhr :get, :only_and_method, :format => :json
60
+ json = ActiveSupport::JSON.decode(response.body)
61
+ json['total'].should eq(34)
62
+ json['order'].should be_nil # root should be changed
63
+ json['custom_root'].should_not be_nil # to user passed root
64
+ json['custom_root'].each do |order|
65
+ order['custom'].should_not be_nil
66
+ order['id'].should be_nil
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "GET 'except_and_method'" do
72
+ it "responds to xhr with user passed total, root, and method" do
73
+ Factory.create(:order)
74
+ xhr :get, :except_and_method, :format => :json
75
+ json = ActiveSupport::JSON.decode(response.body)
76
+ json['total'].should eq(34)
77
+ json['order'].should be_nil # root should be changed
78
+ json['custom_root'].should_not be_nil # to user passed root
79
+ json['custom_root'].each do |order|
80
+ order['custom'].should_not be_nil
81
+ order['created_at'].should be_nil
82
+ order['updated_at'].should be_nil
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ context "ActiveRecord Relation with Nested Resource" do
89
+ describe "GET 'index_with_nested_resource'" do
90
+ it "responds to xhr with nested resource" do
91
+ order = Factory.create(:order_with_items)
92
+ xhr :get, :index_with_nested_resource, :format => :json
93
+ json = ActiveSupport::JSON.decode(response.body)
94
+ json['total'].should eq(1)
95
+ json['order'].should_not be_nil
96
+ json_order = json['order'].first
97
+ json_order['name'].should_not be_nil
98
+ json_order['items'].should be_a(Array)
99
+ json_order['items'].size.should eq(order.items.count)
100
+ json_order['items'].first['name'].should_not be_nil
101
+ end
102
+ end
103
+ end
104
+
105
+ #UNCOMMENT config/application.rb -> require "will_paginate" to test
106
+ context "Pagination with will_paginate" do
107
+ describe "GET 'index_will_paginate'" do
108
+ it "responds with total_entries" do
109
+ 50.times{ |n| Factory.create(:order) }
110
+ 50.times{ |n| Factory.create(:order, :name => "Outlier #{n}") }
111
+ xhr :get, :index_will_paginate, :format => :json
112
+ json = ActiveSupport::JSON.decode(response.body)
113
+ json['total'].should eq(50)
114
+ json['order'].should_not be_nil
115
+ json_order = json['order'].size.should eq(25)
116
+ end
117
+ end
118
+ end
119
+
120
+ #UNCOMMENT config/application.rb -> require "kaminari" to test
121
+ # context "Pagination with kaminai" do
122
+ # describe "GET 'index_kaminari_pagination'" do
123
+ # it "responds with total_count" do
124
+ # 50.times{ |n| Factory.create(:order) }
125
+ # 50.times{ |n| Factory.create(:order, :name => "Outlier #{n}") }
126
+ # xhr :get, :index_kaminari_pagination, :format => :json
127
+ # json = ActiveSupport::JSON.decode(response.body)
128
+ # json['total'].should eq(50)
129
+ # json['order'].should_not be_nil
130
+ # json_order = json['order'].size.should eq(25)
131
+ # end
132
+ # end
133
+ # end
134
+
135
+ context "Single Resource" do
136
+
137
+ describe "GET 'edit'" do
138
+ it "responds to xhr with formatted json" do
139
+ order = Factory.create(:order)
140
+ xhr :get, :edit, :id => order.id, :format => :json
141
+ json = ActiveSupport::JSON.decode(response.body)
142
+ json['total'].should be_nil
143
+ json['data'].should_not be_nil
144
+ json['data']['id'].should eq(order.id)
145
+ end
146
+ end
147
+
148
+ describe "GET 'edit_change_root'" do
149
+ it "responds to xhr with formatted json" do
150
+ order = Factory.create(:order)
151
+ xhr :get, :edit_change_root, :id => order.id, :format => :json
152
+ json = ActiveSupport::JSON.decode(response.body)
153
+ json['total'].should be_nil
154
+ json['data'].should be_nil
155
+ json['custom_root'].should_not be_nil
156
+ json['custom_root']['id'].should eq(order.id)
157
+ end
158
+ end
159
+
160
+ describe "GET 'edit_with_method'" do
161
+ it "responds to xhr with formatted json" do
162
+ order = Factory.create(:order)
163
+ xhr :get, :edit_with_method, :id => order.id, :format => :json
164
+ json = ActiveSupport::JSON.decode(response.body)
165
+ json['total'].should be_nil
166
+ json['data'].should be_nil
167
+ json['custom_root'].should_not be_nil
168
+ json['custom_root']['id'].should eq(order.id)
169
+ json['custom_root']['custom'].should_not be_nil
170
+ end
171
+ end
172
+
173
+ describe "GET 'edit_only_and_method'" do
174
+ it "responds to xhr with formatted json" do
175
+ order = Factory.create(:order)
176
+ xhr :get, :edit_only_and_method, :id => order.id, :format => :json
177
+ json = ActiveSupport::JSON.decode(response.body)
178
+ json['total'].should be_nil
179
+ json['data'].should be_nil
180
+ json['custom_root'].should_not be_nil
181
+ json['custom_root']['id'].should eq(order.id)
182
+ json['custom_root']['custom'].should_not be_nil
183
+ json['custom_root']['created_at'].should be_nil
184
+ json['custom_root']['updated_at'].should be_nil
185
+ end
186
+ end
187
+
188
+ describe "GET 'edit_except_and_method'" do
189
+ it "responds to xhr with formatted json" do
190
+ order = Factory.create(:order)
191
+ xhr :get, :edit_except_and_method, :id => order.id, :format => :json
192
+ json = ActiveSupport::JSON.decode(response.body)
193
+ json['total'].should be_nil
194
+ json['data'].should be_nil
195
+ json['custom_root'].should_not be_nil
196
+ json['custom_root']['id'].should eq(order.id)
197
+ json['custom_root']['custom'].should_not be_nil
198
+ json['custom_root']['created_at'].should be_nil
199
+ json['custom_root']['updated_at'].should be_nil
200
+ end
201
+ end
202
+
203
+ describe "GET 'edit_with_nested_resource'" do
204
+ it "responds to xhr with nested resource" do
205
+ order = Factory.create(:order_with_items)
206
+ xhr :get, :edit_with_nested_resource, :id => order.id, :format => :json
207
+ json = ActiveSupport::JSON.decode(response.body)
208
+ json['data'].should_not be_nil
209
+ json_order = json['data']
210
+ json_order['items'].should be_a(Array)
211
+ json_order['items'].size.should eq(order.items.count)
212
+ json_order['items'].first['name'].should_not be_nil
213
+ end
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Order do
4
+
5
+ # UNCOMMENT config/application.rb -> require "will_paginate" to test
6
+ it "paginates with will_paginate" do
7
+ 50.times{ |n| Factory.create(:order) }
8
+ 50.times{ |n| Factory.create(:order, :name => "Outlier #{n}") }
9
+ @orders = Order.where("name LIKE ?", '%order%').paginate(:page => 1, :per_page => 40)
10
+ @orders.count.should eq(50)
11
+ @orders.size.should eq(40)
12
+ Order.count.should eq(100)
13
+ end
14
+
15
+ # UNCOMMENT config/application.rb -> require "kaminari" to test
16
+ # it "paginates with kaminari" do
17
+ # 50.times{ |n| Factory.create(:order) }
18
+ # 50.times{ |n| Factory.create(:order, :name => "Outlier #{n}") }
19
+ # @orders = Order.where("name LIKE ?", '%order%').page(1).per(40)
20
+ # @orders.size.should eq(40)
21
+ # @orders.total_count.should eq(50)
22
+ # Order.count.should eq(100)
23
+ # end
24
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe ExtjsRenderer do
4
+ it "should be valid" do
5
+ ExtjsRenderer.should be_a(Module)
6
+ end
7
+ end
@@ -0,0 +1,24 @@
1
+ # Configure Rails Envinronment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
+ require "rails/test_help"
6
+ require "rspec/rails"
7
+ require 'factory_girl_rails'
8
+
9
+ Rails.backtrace_cleaner.remove_silencers!
10
+
11
+ # Run any available migration
12
+ ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
13
+
14
+ # Load support files
15
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
16
+
17
+ RSpec.configure do |config|
18
+ # == Mock Framework
19
+ config.mock_with :rspec
20
+
21
+ # turn on transactions for factory use
22
+ config.use_transactional_fixtures = true
23
+
24
+ end
@@ -0,0 +1,14 @@
1
+ FactoryGirl.define do
2
+ factory :order do
3
+ sequence(:name){|n| "order #{n}" }
4
+ end
5
+
6
+ factory :item do
7
+ sequence(:name){|n| "item #{n}" }
8
+ order nil
9
+ end
10
+
11
+ factory :order_with_items, :parent => :order do |order|
12
+ order.after_create {|o| 5.times { Factory.create(:item, :order => o) } }
13
+ end
14
+ end