rails_jskit 5.0.0 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7cfada1cab937ef9b8502560244c406545178417
4
- data.tar.gz: 9a1decf703ee7a5d321542c7acf32ad72a674efd
3
+ metadata.gz: ad1c775799b28a7db824596cc46bd3a408e4dfe4
4
+ data.tar.gz: 5705864e3a14dfc72b20cd65bceee5efb1c09107
5
5
  SHA512:
6
- metadata.gz: 1cf188610748aa597bd9a46c3655204bab5e37aaf6fb98b5230e9de373184d40c13b6467b51e8f6b76b56931989f7c65fdc7be07fd52083a99de451803c2b760
7
- data.tar.gz: 1e69b27142a52ab2eca03eeffda2c6d91e555153a2ee3fe86a6e06e1a090eaccf216eb1c010fc20f408f724df4fae322e154534fe8a82deb9b9c81c8bb34171b
6
+ metadata.gz: 57bc99de58e79d624bfbc3b3b98ed98d29bb60189df8aeed45bcf7df6e5be5c0f1b7688fe4c343dd5e6a329b8e5cd0d9d9731c7d46240550a2321a9978bbb1a3
7
+ data.tar.gz: 8f7c5caba135044cf229c8b43e7e8b916e258ce782e6a5307ee9109c4142f8e291a22ca80c61a88207aa7d0dcd1efa6908af4d8f51d7399ec9a369dfbaf23a49
data/README.md CHANGED
@@ -3,214 +3,596 @@
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/rails_jskit.svg)](http://badge.fury.io/rb/rails_jskit)
5
5
 
6
- rails_jskit is a gem that let's you seamlessly integrate rails with [JSkit](https://github.com/daytonn/jskit). View the example repo [here](https://github.com/daytonn/rails_jskit-example) or see it in action [here](https://jskit-rails-example.herokuapp.com/)
7
-
8
- [Documentation](http://daytonn.github.io/rails_jskit/documentation.html)
9
-
10
- ### Dependencies
11
- * [lodash](https://lodash.com/) or [underscore](http://underscorejs.org/)
12
- * [jquery](https://jquery.com/) or equivalent
6
+ rails_jskit is a gem that let's you seamlessly integrate rails with [JSkit](https://github.com/daytonn/jskit). View the example repo [here](https://github.com/daytonn/rails_jskit-example).
7
+
8
+ * [Online Documentation](http://daytonn.github.io/rails_jskit/documentation.html)
9
+ * [Dependencies](#dependencies)
10
+ * [Installation](#installation)
11
+ - [Automatic Installation](#automatic-installation)
12
+ - [Manual Installation](#manual-installation)
13
+ * [Documentation](#getting-started)
14
+ - [Application Object](#application-object)
15
+ * [Dispatcher](#dispatcher)
16
+ * [Controllers Object](#controllers-object)
17
+ * [Controller Factories](#controller-factories)
18
+ - [Controllers](#controllers)
19
+ * [Actions](#actions)
20
+ * [Mapped Actions](#mapped-actions)
21
+ * [The `all` Action](#the-all-action)
22
+ * [Creating an Application Controller](#creating-an-application-controller)
23
+ * [Passing Data To Actions](#passing-data-to-actions)
24
+ * [Elements](#elements)
25
+ * [Events](#events)
26
+
27
+ * [Configuration](#configuration)
28
+ * [Testing](#getting-started)
29
+ - [Controller Factories](#controller-factories)
30
+ - [Testing Actions](#testing-actions)
31
+ - [Testing Elements](#testing-elements)
32
+ - [Testing Events](#testing-events)
33
+
34
+ Dependencies
35
+ ------------
13
36
 
14
- Make sure that the dependencies is required in your `application.js` file.
37
+ RailsJskit requires `jquery` (or equivalent) and `lodash` (or equivalent). Require them in your `app/assets/javascripts/application.js` before `//= require rails_jskit`.
15
38
 
16
39
  ```js
40
+ // app/assets/javascripts/application.js
17
41
  //= require lodash
18
42
  //= require jquery
19
43
  ```
20
44
 
21
- -- or --
22
-
23
- ```js
24
- //= require underscore
25
- //= require zepto
26
- ```
27
-
28
45
  Installation
29
46
  ------------
30
47
 
31
48
  Add `rails_jskit` to your Gemfile:
32
49
 
33
- ```rb
50
+ ```ruby
51
+ # Gemfile
34
52
  gem "rails_jskit"
35
53
  ```
36
54
 
37
- Bundle it up:
55
+ Bundle it up
38
56
 
39
57
  ```sh
40
58
  bundle install
41
59
  ```
42
60
 
43
- Usage
44
- -----
61
+ ###Automatic Installation
45
62
 
46
- Add the `jskit` helper to your layout (i.e. `app/views/layouts/application.html.erb`):
63
+ RailsJskit comes with handy generators to get you started quickly. Use the generator to install jskit:
47
64
 
48
- ```html
49
- <%= jskit %>
65
+ ```sh
66
+ rails generate jskit:install
50
67
  ```
51
68
 
52
- Add the jskit javascript (i.e. `app/assets/javascripts/application.js`):
69
+ Or you can install it the good old-fashioned way, by hand:
70
+
71
+ ###Manual Installation
72
+
73
+ Create a `app/assets/javascripts/controllers/` directory and add rails_jskit to `app/assets/javascripts/application.js`:
53
74
 
54
75
  ```js
76
+ // app/assets/javascripts/application.js
77
+ ...
55
78
  //= require rails_jskit
79
+ //= require_tree ./controllers
80
+ ```
81
+
82
+ Add `jskit` to your application layout:
83
+
84
+ ```erb
85
+ # app/views/layouts/application.html.erb
86
+ <!DOCTYPE html>
87
+ <html>
88
+ <head>
89
+ <title>JskitExample</title>
90
+ <%= stylesheet_link_tag 'application', media: 'all' %>
91
+ <%= csrf_meta_tags %>
92
+ </head>
93
+ <body>
94
+ <%= yield %>
95
+ <%= javascript_include_tag 'application' %>
96
+ <%= jskit %>
97
+ </body>
98
+ </html>
56
99
  ```
57
100
 
58
- That's it, now all controller actions will be triggered on the `JSkit` dispatcher.
101
+ **That's it!** You're ready to use RailsJskit.
102
+
103
+ Now all your controllers will be loaded at runtime but nothing will execute until events are dispatched.
104
+
105
+ Documentation
106
+ -------------
107
+
108
+ ### Application Object
109
+
110
+ RailsJskit will automatically create a JSkit application object for you, using the configured `app_namespace` for the global variable name _(defaults to "App")_. This global namespace provides you a way to interact with your JSkit application. You can #{link_to "configure", "#configuration"} this setting in your initializer `(config/initializers/rails_jskit.rb)`.
111
+
112
+ #### Dispatcher
113
+
114
+ Every JSkit application has a `Dispatcher` object. This object is responsible for registering and triggering events in your application. In general you don't interact directly with the application's Dispatcher, though it's important to know what it is and what it's doing. By default, every controller created by your application will have it's own reference to the Dispatcher object. A controller's actions will automatically be registered on the Dispatcher when it's created, so you shouldn't need to interact with the Dispatcher directly.
115
+
116
+ #### Controllers Object
117
+
118
+ Every JSkit application also has a `Controllers` object that stores the Controllers instantiated by your application at runtime. Everytime you create a controller, an instance is created on the controllers object:
119
+
120
+ ```ruby
121
+
122
+ // app/assets/javascripts/controllers/posts_controller.js
123
+ App.createController("Posts", {
124
+ ...
125
+ });
126
+
127
+ App.Controllers.Posts;// Instantiated Posts controller object
128
+ ```
129
+
130
+ #### Controller Factories
131
+
132
+ In addition to instances of each controller, the factory used to create the controller is stored on the application object itself. The factory is a function that will create a freshly initialized controller, useful in testing environments:
133
+
134
+ ```ruby
135
+
136
+ // app/assets/javascripts/controllers/posts_controller.js
137
+ App.createController("Posts", {
138
+ ...
139
+ });
140
+
141
+ App.PostsController;// Factory function to create fresh Posts controller objects
142
+ ```
59
143
 
60
144
  ### Controllers
61
145
 
62
- JSkit offers controllers as a basic building block for JavaScript functionality. Making a folder inside `app/assets/javascripts` named `controllers` is a great place to put these:
146
+ The basic component of JSkit is the Controller. Controllers allow you to coordinate JavaScript execution with your Rails controllers. For example, assuming you have a `PostsController` in `app/controllers/posts_controller.rb`.
63
147
 
64
- ```sh
65
- mkdir app/assets/javascripts/controllers
148
+ ```ruby
149
+ # app/controllers/posts_controller.rb
150
+ class PostsController < ApplicationController
151
+ def index
152
+ render :index
153
+ end
154
+ end
66
155
  ```
67
156
 
68
- Now simply require that entire directory in your `application.js` file:
157
+ #### Actions
158
+
159
+ To define JavaScript for that controller, create a corresponding JSkit controller in `app/assets/javascripts/controllers/posts_controller.js` and define it's `actions`. The actions array tells JSkit which functions you want automatically wired to the controller's events. If you wish to run javascript on the `index` action of the `PostsController`, it would look something like this:
69
160
 
70
161
  ```js
71
- //= require_tree ./controllers
162
+ // app/assets/javascripts/controllers/posts_controller.js
163
+ App.createController("Posts", {
164
+ actions: ["index"]
165
+
166
+ index: function() {
167
+ // behavior for posts#index
168
+ }
169
+ });
72
170
  ```
73
171
 
74
- #### Events
172
+ Now whenever your `PostsController` renders the `index` action, the JSkit controller's index method will execute. It's that simple.
173
+
174
+ #### Mapped Actions
175
+
176
+ You may find yourself wanting to wire up an action with a different function name than it's corresponding rails controlller, or you may want to assign the same function to multiple actions. This can be acheived by using a mapped action:
75
177
 
76
- There are three events triggered on every page rendered: a global event, a controller event and an action event. Given a `Posts` controller, when rendering the `index` action, you will notice the three events triggered where the `<%= jskit %>` snippet was placed:
178
+ ```js
179
+ // app/assets/javascripts/controllers/posts_controller.js
180
+ App.createController("Posts", {
181
+ actions: [{
182
+ edit: "setupForm",
183
+ create: "setupForm",
184
+ update: "setupform"
185
+ }],
186
+
187
+ ...
188
+ setupForm: function() {
189
+ // form setup
190
+ }
191
+ ...
192
+ });
193
+ ```
194
+
195
+ This will wire the three events `controllers:posts:edit`, `controllers:posts:create`, and `controllers:posts:upate` to the `setupForm` function.
196
+
197
+ This simple convention is flexible enough to accomplish any sane JavaScript task for a given action.
198
+
199
+ _Note: you can mix and match objects and strings within the actions array but it's probably best to define the string actions first and pass an object as the last item in the array. This is only for readability as JSkit does not care about the position of the actions in the array._
77
200
 
78
201
  ```js
79
- App.Dispatcher.trigger("controller:application:all");
80
- App.Dispatcher.trigger("controller:pages:all");
81
- App.Dispatcher.trigger("controller:pages:index");
202
+ ...
203
+ actions: [
204
+ "index",
205
+ "show",
206
+ {
207
+ edit: "setupForm",
208
+ create: "setupForm",
209
+ update: "setupForm"
210
+ }
211
+ ]
82
212
  ```
83
213
 
84
- This allows you to integrate your JavaScript at key points in your rails application with minimal coupling. An event triggered with no corresponding `JSkit` controller or action defined has no effect.
214
+ #### The `all` action
85
215
 
86
- #### Application Controller
216
+ There are times when you want a bit of JavaScript to run for every action of a given controller. In this case you can define an `all` method on the controller which will automatically be triggered on every action of the controller:
87
217
 
88
- It's common to have some JavaScript that runs on every page of your application. In the past, you may have slapped random bits of code inside a jQuery `$(document).ready` block but not with JSkit. JSkit makes an explicit yet minimally coupled connection between your Rails app and your client-side code. To define application-wide behavior, define an application controller in `app/assets/controller/application_controller.js`:
218
+ ```js
219
+ ...
220
+ all: function() {
221
+ console.log("Happens on every action");
222
+ }
223
+ ...
224
+ ```
225
+
226
+ _Note: you don't have to add `all` to the actions array, JSkit knows what you mean._
227
+
228
+ #### Creating an Application Controller
229
+
230
+ In some cases, you may want some JavaScript to run on every single page of your application. Something like fading out flash notifications, or instantiating dynamic menus or something of that nature. In this case you can create an Application Controller at: `app/assets/javscripts/controllers/application_controller.js`
89
231
 
90
232
  ```js
233
+ // app/assets/javscripts/controllers/application
91
234
  App.createController("Application", {
92
235
  all: function() {
93
- // This handler will be triggered on all pages
236
+ setTimeout(function() {
237
+ $("#notifications").fadeOut();
238
+ }, 3000);
239
+
240
+ $("#menu").menuify();
94
241
  }
95
242
  });
96
243
  ```
97
244
 
98
- The `all` method is automatically wired to the `controller:application:all` event, which is triggered on each page via the `<%= jskit %>` snippet. You now have a simple, testable controller to define behavior in your application.
245
+ There is nothing special about this controller except the fact that RailsJskit will trigger the `controller:application:all` event on every action of every controller. Which means that the `all` method will execute on every page.
246
+
247
+ #### Passing Data To Actions
248
+
249
+ Sometimes you may find yourself wanting to pass data from the Rails side of your application to the client side. The JSkit event system accounts for this and RailsJskit provides a simple interface to this functionality. JSkit has three payload methods, which are available to your application's controllers. The three methods correspond to the three levels of triggered events on any given page.
99
250
 
100
- All other controllers are defined in the same way, the only difference is that your other controllers will have actions defined. Assuming you have a `Posts` controller in ruby, whose index action needs a bit of JavaScript to spice up the template. You would simply create a corresponding `Posts` controller in `app/assets/javascripts/posts_controller.js`:
251
+ 1. `set_app_payload` (sent with "controllers:application:all")
252
+ 2. `set_controller_payload` (sent with "controllers:[controller name]:[action name]")
253
+ 3. `set_action_payload` (sent with "controllers:[controller name][action name]")
254
+
255
+ Let's assume you want to pass devise's `current_user` object to the application controller. For this you would use `app_payload`
256
+
257
+ ```ruby
258
+ # app/controllers/application_controller.rb
259
+ class ApplicationController < ActionController::Base
260
+ before_action :jskit_app_payload
261
+
262
+ private
263
+
264
+ def jskit_app_payload
265
+ set_app_payload(current_user)
266
+ end
267
+ end
268
+ ```
269
+
270
+ This will pass the `current_user` as JSON in the `controllers:application:all` event:
101
271
 
102
272
  ```js
273
+ App.Dispatcher.trigger("controller:application:all", { email: "user@example.com", first_name: "John", last_name: "Smith"... });
274
+ ```
275
+
276
+ Your application controller can make use of this data by assigning the argument to the action function:
277
+
278
+ ```js
279
+ // app/assets/javascripts/controllers/application_controller.js
280
+ App.createController("Application", {
281
+ all: function(currentUser) {
282
+ App.currentUser = currentUser;// { email: "user@example.com", first_name: "John", last_name: "Smith"... }
283
+ }
284
+ });
285
+ ```
286
+
287
+ These payload methods will take any number of arguments and pass them in order to the event handler. This allows for a simple but flexible way to pass data to your client-side application.
288
+
289
+ The `set_controller_payload` method and the `set_action_payload` work in the same way only they pass data to their specific events.
290
+
291
+ ```ruby
292
+ # app/controllers/posts_controller.rb
293
+ class PostsController < ApplicationController
294
+ before_action :jskit_controller_payload
295
+
296
+ def index
297
+ set_action_payload("Data from the PostsController#index action")
298
+ end
299
+
300
+ private jskit_controller_payload
301
+
302
+ def jskit_controller_payload
303
+ set_controller_payload("Data from the PostsController")
304
+ end
305
+ end
306
+ ```
307
+
308
+ This data can be accessed in the JSkit controller like so:
309
+
310
+ ```js
311
+ // app/assets/javascript/controllers/posts_controller.js
103
312
  App.createController("Posts", {
104
313
  actions: ["index"],
105
-
106
- index: function() {
107
- // do stuff on the index page
314
+
315
+ all: function(message) {
316
+ console.log(message);// "Data from the PostsController"
317
+ },
318
+
319
+ index: function(message) {
320
+ console.log(message);// "Data from the PostsController#index action"
108
321
  }
109
322
  });
110
323
  ```
111
324
 
112
- Here you can see that the `actions` array tells JSkit to wire up the `index` method to the `controller:posts:index` event. This event is automatically fired by the `<%= jskit %>` snippet.
325
+ #### Elements
113
326
 
114
- #### Mapped Events
327
+ It's guaranteed you'll end up saving a reference to an `HTMLElement` wrapped in `jQuery` _(the proverbial jQuery burrito)_. You do this so often, it really helps to have a shorthand for doing so. Consider the following code:
115
328
 
116
- Sometimes you may want to map an action to a method with a different name, or you may want to map multiple actions to the same method. This is accomplished using mapped actions. Instead of using a string in the actions array, use an object to map the action name to the controller's method:
329
+ ```js
330
+ // app/assets/controllers/posts_controller.js
331
+ App.createController("Posts", {
332
+ actions: ["index"],
333
+
334
+ cacheElements: function() {
335
+ this.$postList = $("ul#posts");
336
+ this.$commentToggleLink = $("a.comment-toggle");
337
+ this.$modalWindow = $("#modal-window");
338
+ this.$modalCloseButton = $("#modal-window-close");
339
+ },
340
+
341
+ index: function() {
342
+ this.cacheElements();
343
+ // do stuff with elements
344
+ }
345
+ });
346
+ ```
347
+
348
+ This is generally pretty clean code. It's easy to read and it's simple. The problem is that we're going to want to do the same thing in other actions. We can use the same `cacheElements` method but we may not need all the selectors.
349
+
350
+ If we do want to scope elements to actions, we'll need a way to scope the selected elements to specific actions. JSkit allows you to define this behavior with a simple `elements` object on the controller. Which looks something like this:
117
351
 
118
352
  ```js
353
+ // app/assets/controllers/posts_controller.js
119
354
  App.createController("Posts", {
120
- actions: [
121
- "index",
122
- { new: "setupForm" },
123
- { edit: "setupForm" },
124
- { create: "setupForm" }
125
- ],
126
-
355
+ elements: {
356
+ index: {
357
+ postList: "ul#posts",
358
+ commentToggleLink: "a.comment-toggle",
359
+ modalWindow: "#modal-window",
360
+ modalCloseButton: "#modal-window-close"
361
+ }
362
+ },
363
+
127
364
  index: function() {
128
- // do stuff on the index page
365
+ // do stuff with elements
366
+ }
367
+ });
368
+ ```
369
+
370
+ This keeps all the DOM selection one simple structure that cuts down on the clutter.
371
+
372
+ _Note: all keys under each action will be set as variables prefixed with the `$` to indicate that it's a `jQuery` wrapped set._
373
+
374
+ The above example would create three variables on the controller object when the `index` action is triggered:
375
+
376
+ ```js
377
+ // app/assets/controllers/posts_controller.js
378
+ App.createController("Posts", {
379
+ elements: {
380
+ index: {
381
+ postList: "ul#posts",
382
+ commentToggleLink: "a.comment-toggle",
383
+ modalWindow: "#modal-window",
384
+ modalCloseButton: "#modal-window-close"
385
+ }
129
386
  },
130
-
131
- setupForm: function() {
132
- // setup the posts form
387
+
388
+ index: function() {
389
+ this.$postList;
390
+ this.$commentToggleLink;
391
+ this.$modalWindow;
392
+ this.$modalCloseButton;
133
393
  }
134
394
  });
135
395
  ```
136
396
 
137
- Here you can see that the `new`, `edit`, and `create` actions are all being wired up to the same method `setupForm`. This allows you to reuse common behavior that is needed accross multiple actions.
397
+ #### Events
138
398
 
139
- Finally, you may wish to have some functionality that runs on every action of a controller, to do this, simply define an all method. The `all` method is automatically wired to the `controller:<controller name>:all` event:
399
+ Another common piece of boilerplate code is registering for events on `jQuery` wrapped elements. You know, the meat and potatoes of js development. JSkit has a novel way of tidying up event registration as well. An action's elements can be wired up to event handler functions (defined on the controller) by adding them to the element key's value as an array (tuple):
140
400
 
141
401
  ```js
402
+ // app/assets/controllers/posts_controller.js
142
403
  App.createController("Posts", {
143
- ...
144
-
145
- all: function() {
146
- // do something on every action of the controller
404
+ elements: {
405
+ index: {
406
+ launchModalButton: ["#launch-modal", { click: "openModalWindow" }],
407
+ modalCloseButton: ["#modal-window-close", { click: "closeModalWindow" }]
408
+ }
147
409
  },
148
-
149
- ...
410
+
411
+ openModalWindow: function() {
412
+ this.$modalWindow.removeClass("hidden");
413
+ },
414
+
415
+ closeModalWindow: function() {
416
+ this.$modalWindow.addClass("hidden");
417
+ }
150
418
  });
151
419
  ```
152
420
 
153
- This event structure is a simple and powerful way to coordinate your Rails application with the client-side code.
421
+ This is a simple way reduce some of the repetetive code in your everyday JavaScript. It's also tested in JSkit itself, so you don't need to test that the events were registered properly.
154
422
 
155
- ### Event Payloads
423
+ _Note: if you are not doing anything else in an action but wiring elements and events, you can skip adding the action to the `actions` array, and creating a function for that action._
156
424
 
157
- In addition to simply triggering events, you may optionally pass data to these events. You can pass arbitrary data to any of the three events triggered on page render. To pass data to the application controller's `all` event:
425
+ ##### Multiple Events
158
426
 
427
+ It is also possible to register multiple events on a given element, to do so simply add event keys to the event object for the given action:
159
428
 
160
- ```rb
161
- class ApplicationController < ApplicationController
162
- before_action :set_jskit_payload
163
-
164
- ...
165
-
166
- private
167
-
168
- def set_jskit_payload
169
- set_app_payload(current_user)
170
- end
171
- end
429
+ ```js
430
+ // app/assets/javscripts/controllers/posts_controller.js
431
+ App.createController("Posts", {
432
+ elements: {
433
+ index: {
434
+ nameField: ["input#name", {
435
+ change: "handleNameFieldChange",
436
+ keyup: "handleNameFieldKeyup"
437
+ }]
438
+ }
439
+ },
440
+
441
+ handleNameFieldChange: function(evnt) {
442
+ // handle name field change
443
+ },
444
+
445
+ handleNameFieldKeyup: function(evnt) {
446
+ // handle name field keyup
447
+ }
448
+ });
172
449
  ```
173
450
 
174
- This will pass the current user object to the `Application` controller. You can also pass multiple values:
451
+ Configuration
452
+ -------------
175
453
 
176
- ```rb
177
- class ApplicationController < ApplicationController
178
- before_action :set_jskit_payload
179
-
180
- ...
181
-
182
- private
183
-
184
- def set_jskit_payload
185
- set_app_payload(current_user, [1, 2, 3], { some: "hash" })
186
- end
454
+ At this point, RailsJskit only has one setting, the `app_namespace`. If you're fine with the default namespace of `App`, you don't need to change it. Otherwise create an initializer:
455
+
456
+ ```ruby
457
+ # config/initializers/rails_jskit.rb
458
+ RailsJskit.configure do |config|
459
+ config.app_namespace = "MyApp"
187
460
  end
188
461
  ```
189
462
 
190
- This will pass each item in the array as an argument to the event handler on the controller. Note that each item will have `to_json` called on it automatically, so there is no need to do it yourself. The above example will produce the following triggered event:
463
+ Now you can refer to your application globally as `MyApp`.
191
464
 
192
465
  ```js
193
- ...
194
- App.Dispatcher.trigger("controller:application:all", { first_name: "John", last_name: "Doe" }, [1, 2, 3], { "some": "hash" });
195
- ...
466
+ // app/assets/javascripts/controllers/application_controller.js
467
+ MyApp.createController("Posts", {...});
196
468
  ```
197
469
 
198
- This allows you to share data from your Rails app without explicit knowldge of how your client-side code will consume it. You may also set the controller and action event payloads in the same way:
470
+ Testing
471
+ -------
199
472
 
200
- ```rb
201
- class PostsController < ApplicationController
202
- before_action :set_jskit_payload
203
-
204
- def index
205
- set_action_payload("PostsController#index")
206
- end
207
-
208
- private
209
-
210
- def set_jskit_payload
211
- set_controller_payload("PostsController")
212
- end
213
- end
473
+ One of the main advantages of RailsJSkit is that it provides a simple structure that's easily tested. There are however, a few things you need to keep in mind while testing JSkit controllers.
474
+
475
+ When testing, it's important to use the #{link_to "Controller Factories", "#controller-factories"} to create your test subjects. This ensures that you always have a fresh version of the controller that has not been mutated by previous tests. A basic jasmine/mocha style JSkit controller test looks something like this:
476
+
477
+ ```js
478
+ // spec/javscripts/controllers/posts_controller_spec.js
479
+ describe("PostsController", function() {
480
+ var subject;
481
+ beforeEach(function() {
482
+ subject = App.PostsController.create();// creates a fresh controller
483
+ });
484
+
485
+ describe("#index", function() {
486
+ it("has tests", function() {
487
+ expect(true).to.equal(true);
488
+ });
489
+ });
490
+ });
491
+ ```
492
+
493
+ ### Testing Actions
494
+
495
+ Testing actions is straight-forward, since they are just functions on your controller object, you can simply call them and test their behavior:
496
+
497
+ ```js
498
+ // app/assets/javscripts/controller/posts_controller.js
499
+ App.createController("Posts", {
500
+ actions: ["index"],
501
+
502
+ elements: {
503
+ index: {
504
+ pageContainer: "#container",
505
+ }
506
+ },
507
+
508
+ index: function(color) {
509
+ this.color = color;
510
+ this.$pageContainer.css("background-color", this.color);
511
+ }
512
+ });
513
+ ```
514
+
515
+ ```js
516
+ // spec/javscripts/controllers/posts_controller_spec.js
517
+ describe("PostsController", function() {
518
+ var subject;
519
+ beforeEach(function() {
520
+ subject = App.PostsController.create();
521
+ });
522
+
523
+ describe("#index", function() {
524
+ it("sets the color variable with the given value", function() {
525
+ subject.index("#FF0000");
526
+ expect(subject.color).to.equal("#FF0000");
527
+ });
528
+
529
+ it("changes the page background color to the given color", function() {
530
+ subject.index("#FF0000");
531
+ expect(subject.$pageContainer.css("background-color")).to.equal("#FF0000");
532
+ });
533
+ });
534
+ });
535
+ ```
536
+
537
+ Obviously this is a contrived example but you can see that testing an action is as simple as testing a function.
538
+
539
+ ### Testing Elements
540
+
541
+ While you don't have to test the functionality of JSkit itself, you may want to assert that a certain action has access to a given element. To do this we can simply test the values in the elements object, without having to add fixtures to the test DOM:
542
+
543
+ ```js
544
+ // spec/javscripts/controllers/posts_controller_spec.js
545
+ describe("PostsController", function() {
546
+ var subject;
547
+ beforeEach(function() {
548
+ subject = App.PostsController.create();
549
+ });
550
+
551
+ describe("#index", function() {
552
+ describe("elements", function() {
553
+ it("saves a reference to the #container element", function() {
554
+ expect(subject.elements.index.pageContainer).to.equal("#container");
555
+ });
556
+ });
557
+ });
558
+ });
214
559
  ```
215
560
 
216
- This should be everything you need to design and test basic client-side interactions with JSkit. If you'd like to see a working example check out [this repo](https://github.com/daytonn/jskit_rails-example).
561
+ ### Testing Events
562
+
563
+ Testing events is just as easy as testing elements:
564
+
565
+ ```js
566
+ // app/assets/javscripts/controllers/posts_controller.js
567
+ App.createController("Posts", {
568
+ elements: {
569
+ index: {
570
+ expandCommentsButton: ["#expand-comments", {
571
+ click: "handleExpandCommentsClick"
572
+ }]
573
+ }
574
+ },
575
+
576
+ handleExpandCommentsClick: function() {
577
+ ...
578
+ }
579
+ });
580
+ ```
581
+
582
+ ```js
583
+ // spec/javscripts/controllers/posts_controller_spec.js
584
+ describe("PostsController", function() {
585
+ var subject;
586
+ beforeEach(function() {
587
+ subject = App.PostsController.create();
588
+ });
589
+
590
+ describe("#index", function() {
591
+ describe("events", function() {
592
+ it("wires up `handleExpandCommentsClick` on click of the $expandCommentsButton", function() {
593
+ expect(subject.events.index.expandCommentsButton[1].click).to.equal("handleExpandCommentsClick");
594
+ });
595
+ });
596
+ });
597
+ });
598
+ ```
@@ -77,17 +77,6 @@ module Jskit
77
77
  "app/assets/javascripts/application.js"
78
78
  end
79
79
 
80
- def add_js_to_manifest
81
- if File.exists? js_manifest
82
- if has_jquery?
83
- insert_into_file js_manifest, "//= require lodash\n", before: "//= require jquery\n" unless has_lodash?
84
- else
85
- append_to_file js_manifest, "//= require lodash\n//= require jquery\n"
86
- end
87
- append_to_file js_manifest, "//= require rails_jskit\n//= require_tree ./controllers\n"
88
- end
89
- end
90
-
91
80
  private
92
81
 
93
82
  def application_js
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_jskit
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dayton Nolan
@@ -28,14 +28,14 @@ dependencies:
28
28
  name: appraisal
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency